Select elements of a list by comparing it to another lists tbad er
Suppose I have the following lists:
prod = {{"x1", {"a", "b", "c", "d"}}, {"x2", {"e", "f",
"g"}}, {"x3", {"h", "i", "j", "k", "l"}}, {"x4", {"m",
"n"}}, {"x5", {"o", "p", "q", "r"}}}
and
sub = {{"m", "n"}, {"o", "p", "r", "q"}, {"g", "f", "e"}};
for each element in sub I want to go through prod and select if the element exist such that I get the following output,
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q","r"}}}
I tried doing:
Table[Select[
prod[[All, 2]][[i]], # == ContainsAny[Map[Sort, sub]][[i]] &], {i,
Length[sub]}]
yet it doesn't work, am I missing something?
4 Answers
A rule-based approach:
patt = List /@ OrderlessPatternSequence @@@ Alternatives @@ sub;
Cases[prod, {x_, y : patt} :> {x, y}]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
And a functional approach:
sel = Outer[ContainsAll, Last /@ prod, sub, 1];
Pick[prod, Or @@@ sel]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
A simpler one:
select[{label_, values_}] := MemberQ[sub, {OrderlessPatternSequence @@ values}]
Pick[prod, select /@ prod]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
You can use the same approach with Select:
Select[prod, select]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
You can also turn prod into an Association using sorted second elements as keys and then use Lookup:
Lookup[Sort/@sub] @ GroupBy[ Sort@*Last] @ prod
{{{"x4", {"m", "n"}}}, {{"x5", {"o", "p", "q", "r"}}}, {{"x2", {"e", "f", "g"}}}}
Make it a function:
ClearAll[lookUp]
lookUp[keys_] := Lookup[Sort /@ keys] @* GroupBy[Sort@*Last]
lookUp[sub] @ prod
{{{"x4", {"m", "n"}}}, {{"x5", {"o", "p", "q", "r"}}}, {{"x2", {"e", "f", "g"}}}}
getMatches[prod_, sub_] := Module[{test},
Scan[(test[Sort[#]] = True) &, sub];
Cases[prod, {_, y_?test}]]
getMatches[prod, sub]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
Also
getMatches[prod_, sub_] := Module[{test},
Scan[(test[Sort[#]] = True) &, sub];
Select[prod, test@*Last]]
sortedsub = Sort /@ sub;
Select[prod, MemberQ[sortedsub, Sort[#[[2]]]] &]
{{"x2", {"e", "f", "g"}}, {"x4", {"m", "n"}}, {"x5", {"o", "p", "q", "r"}}}
Pick. $\\endgroup$ – AccidentalFourierTransform 11 hours ago