8
$\begingroup$

Is it possible to use # in the select function preserving the structure of the list?

Here an example of what I mean. Let's say I want to select all the pairs where the first element is 1:

data1 = {{1, 2}, {1, 3}, {3, 4}, {4, 4}, {5, 2}};
data2 = {{1, 1}, {1,5}, {3, 5}};
all = {data1, data2};

The output of the function would be:

{{{1,2},{1,3}},{{1,1},{1,5}}}

I tried with Select but I'm not able to preserve the list structure. Here some (failed) attempt:

Select[all, #[[1, 1]] == 1 &]

with the output:

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

because, as far as I understand, # refers to the elements of the outer list (which are data1 and data2).

Or

Select[Flatten[all, 1], #[[1]] == 1 &]

with the output

{{1, 2}, {1, 3}, {1, 1}, {1, 5}}

but the list structure is not preserved.

Any tips? I just started using functional programming and I often get stuck on this simple (I assume) stuff.

$\endgroup$
7
$\begingroup$
Select[#, #[[1]] == 1 &] & /@ all
Select[#[[1]] == 1 &] /@ all (* thanks: Mr.Wizard *)
Pick[all, #[[1]] == 1 & /@ # & /@ all]
Pick[all, all[[All, All, 1]], 1]
Map[If[#[[1]] == 1, #, ## &[]] &, all, {2}]

all give

{{{1, 2}, {1, 3}}, {{1, 1}, {1, 5}}}

$\endgroup$
  • 1
    $\begingroup$ Also operator form: Select[#[[1]] == 1 &] /@ all $\endgroup$ – Mr.Wizard Jul 23 '17 at 9:29
  • $\begingroup$ thank you @Mr.Wizard. $\endgroup$ – kglr Jul 23 '17 at 9:39
  • $\begingroup$ IMO, Pick makes a lot of sense here, good one :) $\endgroup$ – Marius Ladegård Meyer Jul 23 '17 at 10:58
  • $\begingroup$ Amazing, thank you guys! :D $\endgroup$ – Fraccalo Jul 23 '17 at 18:25
  • $\begingroup$ @Marius I like Pick too, especially its performance on packed arrays compared to Select/Cases, but with the caveat that it can at times be confusing, e.g. (4946), (59272), (119223). $\endgroup$ – Mr.Wizard Jul 24 '17 at 1:14
7
$\begingroup$

At least for the example given:

Cases[{1, _}] /@ all
{{{1, 2}, {1, 3}}, {{1, 1}, {1, 5}}}
$\endgroup$
7
$\begingroup$
DeleteCases[all, {Except[1], _}, 2]

{{{1, 2}, {1, 3}}, {{1, 1}, {1, 5}}}

Or, more generally:

 DeleteCases[{all, all}, {Except[1], _?AtomQ}, -1] // MatrixForm

enter image description here

$\endgroup$
4
$\begingroup$

You may use Query with Select.

Query[All, Select[First@# == 1 &]]@all
{{{1, 2}, {1, 3}}, {{1, 1}, {1, 5}}}

Hope this helps.

$\endgroup$
3
$\begingroup$

Thank you everyone for your answers, I took all of them and tested their efficiency, below the results with absolute timing, acting on randomly generated lists:

data1 = Transpose@{RandomInteger[10, {10^5}], RandomInteger[10, {10^5}]};
data2 = Transpose@{RandomInteger[10, {10^5}], RandomInteger[10, {10^5}]};
all = {data1, data2};

Select[#, #[[1]] == 1 &] & /@ all
0.216706

Select[#[[1]] == 1 &] /@ all
0.218946

Pick[all, #[[1]] == 1 & /@ # & /@ all]
0.404901

Pick[all, all[[All, All, 1]], 1]
0.004603

Map[If[#[[1]] == 1, #, ## &[]] &, all, {2}]
0.356775

Select[#[[1]] == 1 &] /@ all
0.237376

Cases[{1, _}] /@ all
0.078295

DeleteCases[all, {Except[1], _}, 2]
0.104606

Query[All, Select[First@# == 1 &]]@all
0.183894
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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