Title Keywords in Context

This challenge is based on a problem described in D. Parnas, On the criteria to be used in decomposing systems into modules, and elaborated upon in J. Morris, Real Programming in Functional Languages.

Write a program or function which takes a list of book titles from stdin or as an argument, in a reasonable, convenient format for your language. For example,

Green Sleeves
Time Was Lost


or

("Green Sleeves";"Time Was Lost")


Return or print to stdout an alphabetized list of the keywords, showing their context within the original titles by enclosing each keyword in angle braces (< and >). As with input, output can be in a reasonable format which is convenient for your language- newline-separated lines, a list of strings, etc:

<Green> Sleeves
Time Was <Lost>
Green <Sleeves>
<Time> Was Lost
Time <Was> Lost


Titles will consist of a series of keywords separated by a single space. Keywords will contain only alphabetic characters. Keywords are to be sorted lexicographically. Titles will be unique, and keywords will be unique within each title but the same keyword may exist in several titles. If a keyword exists in more than one title, the output should list each appearance in an arbitrary order. For example, given this input:

A Dugong
A Proboscis


A valid output would be either:

<A> Proboscis
<A> Dugong
A <Dugong>
A <Proboscis>


Or:

<A> Dugong
<A> Proboscis
A <Dugong>
A <Proboscis>


This is - the winner is the shortest solution in bytes. Standard loopholes are disallowed.

• What about if the same keyword occurs more than once in a title? Should the occurrences be in order of appearance, or is arbitrary order permitted? – Peter Taylor Nov 27 '15 at 17:23
• @PeterTaylor: from the spec, "Titles will be unique, and keywords will be unique within each title…" – JohnE Nov 27 '15 at 17:26

Pyth, 2524 22 bytes

VSsm,Rdcd\ QAN:HGjG"<>


Try it online.

Takes input as an array of lines, like ["Green Sleeves","Time Was Lost"].

Explanation

VSsm,Rdcd\ QAN:HGjG"<>   implicit: Q = evaluated input

m       Q                   map input lines:
cd\                         split input line to words
,Rd                          replace each word by pair [word, entire line]
s                          concatenate results for all input lines
S                         sort the array of pairs lexicographically
V                        loop over the array
AN             assign the word to G and the corresponding line to H
jG"<>       put the word between <>
:HG          replace the word by the above in the line and print

• Looks buggy - check the handling of title Time Was Time. – Peter Taylor Nov 27 '15 at 17:24
• @PeterTaylor Quoting from the OP, keywords will be unique within each title. – PurkkaKoodari Nov 27 '15 at 17:25

Japt, 55 bytes

Perhaps this could be made shorter, but I'm not sure how...

P+UqR £XqS m_+S+X) q', n £Xs1+XbS)rXs0,XbS),@"<{X}>")qR


How it works

P+UqR m@XqS m_+S+X) q', n m@Xs1+XbS)rXs0,XbS),@"<{X}>")qR
// Implicit: U = input string, S = a space, P = empty string
UqR m@    // Split input at newlines, then map each item X to:
XqS m_    //  X split at spaces, with each item Z mapped to:
+S+X)     //   Z + a space + X.
P+   q',  // Parse the result as a string, and split at commas. Due to JS's default
// array-to-string conversion (joining with commas), this flattens the array.
n         // Sort the result lexicographically.
m@Xs1+XbS // Map each item X to everything after the first space,
rXs0,XbS  // replacing the original keyword with
@"<{X}>"  // "<" + keyword + ">".
qR        // Join the result with newlines.
// Implicit: output last expression


CJam, 4136 32 bytes

q~{:AS/{A1$/"<>"@**}/}%{'</1=}$p


Test it here.

import Data.List

Usage example: f ["Green Sleeves","Time Was Lost"] -> ["<Green> Sleeves","Time Was <Lost>","Green <Sleeves>","<Time> Was Lost","Time <Was> Lost"].