3
$\begingroup$

I want to select sublists from list1 based on the values found in another list.

list1 = { {1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}, {5, 6, 7, 8}}
list2 = {1, 2, 3, 4}

If the first element of a sublist in list1 is present in list2, then it must be part of the output.

The desired output is:

{{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}}

I tried:

Select[list1, #[[1]] == list2 &]

But then the output is empty.

Who has a suggestion?

$\endgroup$
7
  • $\begingroup$ Select[list1, MemberQ[list2,#[[1]]]] my brackets or ordering might be wrong... $\endgroup$
    – tkott
    Mar 24, 2015 at 13:25
  • 2
    $\begingroup$ Almost. Select[list1, (MemberQ[list2, #[[1]]] &)] $\endgroup$
    – LLlAMnYP
    Mar 24, 2015 at 13:26
  • $\begingroup$ Oops, knew I forgot something, thanks @LLlAMnYP $\endgroup$
    – tkott
    Mar 24, 2015 at 13:40
  • 2
    $\begingroup$ In the old days, we used to code like this: list1 = {{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}, {5, 6, 7, 8}}; list2 = {1, 2, 3, 4}; N0 = Length[list1]; M0 = Length[list2]; lst = {}; For[i = 1, i <= N0, i++, { candidate = list1[[i, 1]]; found = False; For[j = 1, j <= M0, j++, { If[list2[[j]] == candidate, found = True; Break[] ] } ]; If[found, AppendTo[lst, list1[[i]]]] } ]; lst which gives {{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}} nowadays functional programming took all the fun away ;) $\endgroup$
    – Nasser
    Mar 24, 2015 at 13:51
  • 1
    $\begingroup$ @Nasser, my eyes just started to bleed. Code can be funny :) $\endgroup$
    – LLlAMnYP
    Mar 24, 2015 at 13:56

5 Answers 5

5
$\begingroup$

Solutions

As mentioned in the comments you could use

Select[list1, list2~MemberQ~First[#] &]

Another way is to use patterns, i.e.

Cases[list1, {Alternatives @@ list2, __}]

or

Pick[list1, First@Transpose@list1, Alternatives @@ list2]


How the pattern based work:

Alternatives @@ list2
(* Out:  1 | 2 | 3 | 4 *)

i.e. {Alternatives @@ list2, __} is the same as {1 | 2 | 3 | 4,__} which will match either 1, 2, 3 or 4 as the first element of the list. __ matches one of several more elements, whatever they are. Cases tests each element in its first argument (list1) to see if it matches the pattern, then it selects those that match. You can test whether your pattern matches the rights elements like this:

MatchQ[#, {Alternatives @@ list2, __}] & /@ list1
(* Out: {True, True, True, False} *)

Pick[list, sel, patt] selects those elements in list for which the corresponding elements in sel match the pattern patt. First@Transpose@list1 selects the first column from the matrix list1, this is the first element in each sublist. Therefore the pattern patt is just 1 | 2 | 3 | 4.

$\endgroup$
2
$\begingroup$

A few additions to the list of methods in @Pickett's answer:

DeleteCases[#, Except@{Alternatives @@ #2, __}]&[list1, list2]

#[[Flatten@Position[#[[All, 1]], Alternatives @@ #2]]] &[list1, list2]

And an alternative form for Select:

Select[list1, Or @@ Function[{x}, #[[1]] == x] /@ list2 &]
$\endgroup$
2
$\begingroup$

Using Lookup:

Whenever "another" list interacts with the "main" list, it is a potential use case for Lookup.

list1 = {{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}, {5, 6, 7, 8}}
list2 = {1, 2, 3, 4}

lut = GroupBy[list1, First]

<|1 -> {{1, 2, 3, 4}, {1, 2, 5, 6}}, 2 -> {{2, 3, 4, 5}}, 5 -> {{5, 6, 7, 8}}|>

Lookup[lut, list2, Nothing] // Level[#, {-2}] &

{{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}}

$\endgroup$
1
$\begingroup$

A variant of @Syed's solution:

list1 = {{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}, {5, 6, 7, 8}};
list2 = {1, 2, 3, 4};

DeleteCases[{}] @ MapApply[Join] @ 
   Lookup[
      MapApply[{# -> {##}} &] @ list1, 
      list2, 
      {}]

{{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}}

MapApply was introduced in V 13.1

$\endgroup$
0
$\begingroup$

Using Insert and Partition:

f[l1_, l2_] := Map[If[! FreeQ[#[[2]], #[[1, 1]]], #[[1]], Nothing] &, 
               Partition[Insert[#, l2, {# + 1} & /@ Ordering[#]], {2}]] &@l1

Testing the function f:

f[list1, list2]

(*{{1, 2, 3, 4}, {1, 2, 5, 6}, {2, 3, 4, 5}}*)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.