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$

5 Answers 5

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$
5
  • 1
    $\begingroup$ Also operator form: Select[#[[1]] == 1 &] /@ all $\endgroup$
    – Mr.Wizard
    Jul 23, 2017 at 9:29
  • $\begingroup$ thank you @Mr.Wizard. $\endgroup$
    – kglr
    Jul 23, 2017 at 9:39
  • $\begingroup$ IMO, Pick makes a lot of sense here, good one :) $\endgroup$ Jul 23, 2017 at 10:58
  • $\begingroup$ Amazing, thank you guys! :D $\endgroup$
    – Fraccalo
    Jul 23, 2017 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, 2017 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$
5
$\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.