3
$\begingroup$

Starting with something like:

lis = {a, b, {c, d}, e, {f, g}, {h, j, k}, m, n};

...my goal is to operate on lis and get:

{{c,d},{f,g}}

...in other words to extract all the sublists of lis that have two elements (regardless of those elements might be. Thanks for any thoughts.

$\endgroup$
5
  • $\begingroup$ Take a look at Cases. $\endgroup$
    – Kuba
    Sep 28, 2016 at 5:40
  • 2
    $\begingroup$ Cases[lis, {_, _}]. Select[lis, Length@# == 2 &]. Replace[lis, Except[{_, _}] :> (## &[]), 1]. $\endgroup$
    – march
    Sep 28, 2016 at 5:46
  • $\begingroup$ Do you know the length of the target sublists, i.e. length two, or do you want to find sublists of an arbitrary length that is repeated? What would be the output for {a, b, {c, d}, e, {f, g}, {h, j, k}, m, n, {o, p, q}} $\endgroup$
    – Mr.Wizard
    Sep 28, 2016 at 5:47
  • $\begingroup$ Thank you for the fast responses! Mr. Wizard, output of your test case would be {{c,d},{f,g}} $\endgroup$
    – Suite401
    Sep 28, 2016 at 5:48
  • $\begingroup$ DeleteCases[Except[{_, _}]][lis] $\endgroup$
    – Syed
    Apr 22, 2023 at 14:55

1 Answer 1

4
$\begingroup$

@march has already given the answer, but neglected to write one formally. There are multiple ways to do this, but the one that makes most sense to me is this:

Select[lis, (Length[#]==2) &]

I'm going to guess that you're not familiar with some of the syntax here, so I'll break it down a bit.

Select is a function taking in a list follow by a predicate to be applied to elements of the list. A predicate is a function of a single argument which outputs either True or False. The Select method will apply the predicate to each of the elements of the list, and remove those for whom the output is False. Note that it doesn't alter the original list; it just outputs a new one.

Here, the predicate is a pure function: (Length[#] == 2)&. The # is replaced with the first argument that this function is applied to, so for each element el in the list lis, Select is checking to see if Length[el]==2 is True. If it is, then it remains in the list.

We could make a function which takes in the desired sublist length and returns the appropriate predicate:

filterLength[n_]:=(Length[#]==n)&;

Full code:

filterLength[n_]:=(Length[#]==n)&;
lis    = {a, b, {c, d}, e, {f, g}, {h, j, k}, m, n};
newLis0 = Select[lis,filterLength[0]];
newLis2 = Select[lis,filterLength[2]];
newLis3 = Select[lis,filterLength[3]];
Print[newLis0]; Print[newLis2]; Print[newLis3];

Output:

{a,b,e,m,n}
{{c,d},{f,g}}
{{h,j,k}}

Notice that order is preserved.

$\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.