Delete strings: {name, John, John Doe, Doe} to {name, John Doe}
strings = {"name", "John", "John Doe", "Doe"};
Pick[strings,
BitAnd @@ (IdentityMatrix[Length[strings]] +
Boole[Outer[StringFreeQ, strings, strings]]), 1]
{"name", "John Doe"}
Or equivalently:
Pick[strings,
MapIndexed[StringFreeQ[Delete[strings, #2], #] &, strings],
ConstantArray[True, Length[strings] - 1]]
The code below matches only whole words:
strings = {"to", "tomorrow", "name", "John", "John Doe", "Doe"}
Pick[strings,
And @@@ MapIndexed[StringFreeQ[Delete[strings, #2],
" " | StartOfString ~~ # ~~ EndOfString | " "] &, strings]]
{"to", "tomorrow", "name", "John Doe"}
I'll assume that the list will contain strings, not variables:
L = {"name", "John", "John Doe", "Doe"};
Delete element sequences like {"John", "Doe"}
that are together contained in a single string "John Doe"
:
ClearAll[f];
SetAttributes[f, Orderless];
(f[Sequence @@ #, x___] = f[x]) & /@ Select[StringSplit /@ L, Length[#] > 1 &];
f[x___] = {x};
f @@ L
{"John Doe", "name"}
This method does not keep the original sorting order of the list. If this order needs to be kept, we can replace the last line with
SortBy[f @@ L, Position[L, #][[1, 1]] &]
{"name", "John Doe"}
update
In order to deal with multiple mentions of "John", for example, a slight modification to the Orderless
pattern using Repeated ..
:
L = {"name", "John", "John", "John Doe", "Doe"};
ClearAll[f];
SetAttributes[f, Orderless];
(f[Sequence @@ Thread[# ..], x___] = f[x]) & /@
Select[StringSplit /@ L, Length[#] > 1 &];
f[x___] = {x};
SortBy[f @@ L, Position[L, #][[1, 1]] &]
{"name", "John Doe"}
# /. Flatten[Cases[#,
x_ /; StringContainsQ[x, " "] :>
Thread[StringSplit[x] -> Nothing]]] &[{"name", "John",
"John Doe", "Doe"}]
{"name", "John Doe"}