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.

| improve this question | | | | |
$\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}}}

| improve this answer | | | | |
$\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}}}
| improve this answer | | | | |
$\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

| improve this answer | | | | |
$\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.

| improve this answer | | | | |
$\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
| improve this answer | | | | |
$\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.