8
$\begingroup$

We have a list as

list = {{h, {{1, 1, 2}, {1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 3, 1}, {2, 
 2, 1}, {2, 1}}}, {r, {{1, 1, 2}, {3, 4}, {2, 1}, {2, 4}, {2, 1, 
 5}}}};

We wish to have another list containing just pairs:

list = {{h, { {1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 1}}}, {r, { {3, 4}, {2, 1}, {2, 4}}}};

How can we use Pick or Select or other functions for this aim?

Thank you in advance

$\endgroup$

6 Answers 6

4
$\begingroup$

Select can be used to identify pairs in sub-lists, such as

Select[list[[1, 2]], Length@# == 2 &]

(* {{1, 3}, {1, 4}} *)

Then, use Map to apply Select to every sub-list:

{First@#, Select[Last@#, Length@# == 2 &]} & /@ list

(* {{h, {{1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 1}}}, {r, {{3, 4}, {2, 1}, {2, 4}}}} *)
$\endgroup$
1
  • $\begingroup$ I could understand. it is amazing solution. Without using additional IF condition which was in my decesion $\endgroup$ Commented May 3, 2017 at 5:24
13
$\begingroup$

I think you'll find the simple

DeleteCases[list, {_, _, __}, {3}]

to be a bit more efficient...

$\endgroup$
1
  • 2
    $\begingroup$ simple and efficient...+1 winner for me:) $\endgroup$
    – ubpdqn
    Commented May 3, 2017 at 6:59
7
$\begingroup$

Using Apply

f[x_, y_] := {x, y};
f[___] := Nothing;
Apply[f, list, {3}]
$\endgroup$
7
$\begingroup$

Using ReplaceAll (/.)

list /.  {_Integer, _Integer, __} :> Nothing

One needs to carefully specify the replacement rules however, try for example

list /.  {_, _, __} :> Nothing
(* Nothing *)

Rule replacement is actually quite efficient (relatively speaking) in this case, compare the above to @ciao's answer:

testList = Join[Apply[Sequence]@Table[list, 200000]]

(res1 = testList /.  {_Integer, _Integer, __} :> Nothing); // AbsoluteTiming
(* {2.55462, Null} *)
(res2 = DeleteCases[testList, {_, _, __}, {3}]); // AbsoluteTiming
(* {0.769297, Null} *)
res1 == res2
(* True *)

For a solution based on rule replacement a factor of ~3 worse than the (supposedly) fastest method isn't half bad.

$\endgroup$
2
  • 1
    $\begingroup$ One needs to carefully specify the replacement rules... well how about Replace[list, {_, _, __} :> Nothing, {3}]? $\endgroup$
    – LLlAMnYP
    Commented May 3, 2017 at 8:10
  • $\begingroup$ @LLlAMnYP that one works as well but I though it less general (but maybe safer to use) in case of more deeply nested lists $\endgroup$
    – Sascha
    Commented May 3, 2017 at 8:17
6
$\begingroup$

Pattern Matching:

xss = {{h, {{1, 1, 2}, {1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 3, 1}, {2, 
 2, 1}, {2, 1}}}, {r, {{1, 1, 2}, {3, 4}, {2, 1}, {2, 4}, {2, 1, 
 5}}}}
xss //. {xs___, {_Integer, _Integer, __}, ys___} -> {xs, ys}

Test (Special Case, 200000 copies of xss):

xss = {{h, {{1, 1, 2}, {1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 3, 1}, {2, 
     2, 1}, {2, 1}}}, {r, {{1, 1, 2}, {3, 4}, {2, 1}, {2, 4}, {2, 1, 
     5}}}}
testList = Join[Apply[Sequence]@Table[xss, 200000]]
f[xss_] := f[xss] = 
  xss //. {xs___, {_Integer, _Integer, __}, ys___} -> {xs, ys}
AbsoluteTiming[testList // Map[f] ]

enter image description here

$\endgroup$
10
  • 2
    $\begingroup$ Using ReplaceRepeated this way is very inefficient. $\endgroup$
    – Sascha
    Commented May 3, 2017 at 7:21
  • $\begingroup$ The execution time is 0.000057 seconds. {0.000057, {{h, {{1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 1}}}, {r, {{3, 4}, {2, 1}, {2, 4}}}}} $\endgroup$
    – webcpu
    Commented May 3, 2017 at 7:29
  • $\begingroup$ try the same with a longer list e.g. a form of testlist from my answer (maybe with 1000 copies of the original list) $\endgroup$
    – Sascha
    Commented May 3, 2017 at 7:41
  • 2
    $\begingroup$ Memoization is cheating ;-). You are memoizing just three inputs, this is not a representative test. $\endgroup$
    – LLlAMnYP
    Commented May 3, 2017 at 8:01
  • 1
    $\begingroup$ @Sascha precisely. But Map[# //. {xs___, {_Integer, _Integer, __}, ys___} :> {xs, ys} &, testList, {2}] is okay-ish. $\endgroup$
    – LLlAMnYP
    Commented May 3, 2017 at 8:08
5
$\begingroup$

An example with MapAt:

MapAt[Cases[#, _?(Length@# == 2 &)] &, list, {All, 2}]

yielding:

(* {{h, {{1, 3}, {1, 4}}}, {k, {{1, 3}, {2, 1}}}, {r, {{3, 4}, {2, 
    1}, {2, 4}}}}*)
$\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.