# Select list elements based on other list

I am trying to find a nice and clean method to select elements from one list which are in another list or the criteria is based on another list. The ones I want to returned are in listA and the ones that contain the matching criteria are in listB. listA has different dimensions than listB and I only apply the criterion on certain subset say, listA[[All,1]]. Obviously, not all elements in listA[[All,1]] have to be present in listB and not all elements of listB are present in listA[[All,1]] So far, I have come up with the two almost identical methods:

listA = {{"a", 1, 3}, {"b", 3, 4}, {"e", 4, 4}, {"r", 2, 2}}
listB = {"a", "c", "d", "e"}
Function[u, Select[listA, #[[1]] == u &]] /@
Intersection[listA[[All, 1]], listB]
Function[u, Select[listA, #[[1]] == u &]] /@ listB


Obviously the second one returns also empty sublists which need to be deleted. Both suffer from producing an additional dimension {{{"a", 1, 3}}, {{"e", 4, 4}}} which, of cource, can be corrected with flatten. But, I am interested if there is another, a more elegant way, that would keep the structure of listA, without having to figure out at which level to flatten (it is simple in the example above)? (to summarize, I already have a working solution, i am just interesting in other or better ways to do it which I am missing, thank you)

• Somewhat related: 4626. I particularly liked this rules based approach. A similar method using ToAssoication would be worth trying. May 7, 2019 at 2:20

 Select[listA,MemberQ[listB,#[[1]]]&]


{{"a", 1, 3}, {"e", 4, 4}}

You can also use Cases:

Cases[{Alternatives @@ listB, __}] @ listA


{{"a", 1, 3}, {"e", 4, 4}}

You can use an association:

take = Lookup[AssociationThread[#[[All, 1]] -> #], #2, Nothing] &;
take[listA, listB]
(* {{"a", 1, 3}, {"e", 4, 4}} *)

Complement[listA, Extract[listA , #] & /@ Position[Intersection[#, listB ] & /@ listA , {}] ]


{{"a", 1, 3}, {"e", 4, 4}}

Here's a very tolerant version that works without flattening listA. It compares the leaves of the elements of listA (extracted with Level[#, {-1}]) with the elements of listB. This makes it tolerant to reordering of elements in listA as well as arbitrary nesting.

listA = {{"a", 1, 3}, {"b", 3, 4}, {"e", 4, 4}, {"r", 2, 2}};
listB = {"a", "c", "d", "e"};
Select[listA, IntersectingQ[Level[#, {-1}], listB] &]


{{"a", 1, 3}, {"e", 4, 4}}

One more level of nesting:

listA = {{{"a", 1, 3}}, {{"b", 3, 4}}, {{"e", 4, 4}}, {{"r", 2, 2}}};
Select[listA, IntersectingQ[Level[#, {-1}], listB] &]


{{{"a", 1, 3}}, {{"e", 4, 4}}}

Crazy nesting:

listA = {{{{{{{"a", 1, 3}}}}}}, {{"b", 3, 4}}, {{{2}, {{"e"}, 3}, 4, 4}}, {{{{{{{{"r", 2, 2}}}}}}}}};
Select[listA, IntersectingQ[Level[#, {-1}], listB] &]


{{{{{{{"a", 1, 3}}}}}}, {{{2}, {{"e"}, 3}, 4, 4}}}