You can use the Bentley-Clarkson-Levine algorithm that is encoded in Internal`ListMin
to find the maximal elements of your list. To do so, we need to encode the elements as lists of 0s and 1s where the 0s indicate the symbols that are included in the list. For your example this would be
{{a,b,c }, {a,b, d }, {d,e }, { d }, {a }, {a,b, }, { f}}
{{0,0,0,1,1,1}, {0,0,1,0,1,1}, {1,1,1,0,0,1}, {1,1,1,0,1,1}, {0,1,1,1,1,1}, {0,0,1,1,1,1}, {1,1,1,1,1,0}}
Now, consider {a, b, c}
and {a, b}
, or:
{a, b, c} -> {0, 0, 0, 1, 1, 1}
{a, b} -> {0, 0, 1, 1, 1, 1}
For this pair, Internal`ListMin
will remove {0, 0, 1, 1, 1, 1}
because it's "bigger" than {0, 0, 0, 1, 1, 1}
(the function is called Internal`ListMin
, not Internal`ListMax
after all). Using Internal`ListMin
on the list gives:
Internal`ListMin[{{0,0,0,1,1,1}, {0,0,1,0,1,1}, {1,1,1,0,0,1}, {1,1,1,0,1,1}, {0,1,1,1,1,1}, {0,0,1,1,1,1}, {1,1,1,1,1,0}}]
{{0, 0, 0, 1, 1, 1}, {0, 0, 1, 0, 1, 1}, {1, 1, 1, 0, 0, 1}, {1, 1, 1, 1, 1,
0}}
And this corresponds to the original sublists:
Pick[{a, b, c, d, e, f}, #, 0]& /@ %
{{a, b, c}, {a, b, d}, {d, e}, {f}}
in agreement with the expected answer. Putting the above pieces together gives the following function:
PartialMaximum[l:{__List}]:=Module[{ass, un, indexed, s},
un = Union @@ l;
ass = AssociationThread[#, Range @ Length @ #]& @ Apply[Union] @ l;
indexed = Replace[l, ass, {2}];
s = ConstantArray[1, {Length[l], Length[ass]}];
MapIndexed[(s[[First@#2, #1]] = 0)&, indexed];
Pick[un, #, 0]& /@ Internal`ListMin @ s
]
Your example again:
PartialMaximum[{{a,b,c},{a,b,d},{d,e},{d},{a},{a,b},{f}}]
{{a, b, c}, {a, b, d}, {d, e}, {f}}
A larger example:
lst = DeleteDuplicates[RandomSample[Range@200,#]&/@RandomInteger[{1,99},1000]];
PartialMaximum[lst]; //AbsoluteTiming
{0.066836, Null}
In my experiments, this is slightly faster than MrWizard's answer.