15

6

What is the fastest way to make multiple selections from a list? Compiled methods included.

For example, here are two methods for selecting a subset, compared:-

```
biglist = {{5, "e", 500}, {4, "d", 400},
{3, "c", 300}, {2, "b", 200}, {1, "a", 100}};
subset = {2, 5, 4};
Cases[biglist, {#, __}] & /@ subset
```

{{{2, "b", 200}}, {{5, "e", 500}}, {{4, "d", 400}}}

```
Cases[biglist, {Apply[Alternatives, subset], __}]
```

{{5, "e", 500}, {4, "d", 400}, {2, "b", 200}}

Only first method returns items in the order matched in the subset list, but it is much slower:-

```
n = 10000;
biggerlist = Map[{#, FromCharacterCode[Mod[# - 1, 26] + 97], #*100} &,
Range[n]];
unsortedbiglist = RandomSample[biggerlist, n];
unsortedsubset = RandomSample[Range[n], Round[n/10]];
Row[{First[Timing[selection1 = Map[Cases[unsortedbiglist, {#, __}] &,
unsortedsubset];]], " seconds"}]
```

1.123 seconds

```
Row[{First[Timing[selection2 = Cases[unsortedbiglist,
{Apply[Alternatives, unsortedsubset], __}];]], " seconds"}]
```

0.171 seconds

The selections are the same, but differently ordered:-

```
SameQ[Flatten[selection1, 1],
Extract[selection2,
Flatten[Map[Position[First /@ selection2, #] &,
unsortedsubset], 1]]]
```

True

Including the sorting routine in the selection process still gives a better timing:-

```
Row[{First[Timing[selection3 = Function[selection2,
Extract[selection2,
Flatten[Map[Position[First /@ selection2, #] &,
unsortedsubset], 1]]][Cases[unsortedbiglist,
{Apply[Alternatives, unsortedsubset], __}]];]], " seconds"}]
```

0.359 seconds

```
SameQ[Flatten[selection1, 1], selection3]
```

True

Nevertheless, only the slow `Cases`

method returns `{}`

when there are unmatched subset items, which is sometimes useful.

Ideas for speedy selections would be great.

I updated the code and reran the test and timing. Feel free to revert if it's not to your liking. – jVincent – 2013-02-07T13:37:36.550

@jVincent Thanks, looks good to me. – Leonid Shifrin – 2013-02-07T13:44:55.043

Very nice. Also, adding

`... sub] /. {} -> {{}}`

to the last line makes it handle non-matching sublist items the same as`Cases`

. – Chris Degnen – 2013-02-07T14:19:59.373@ChrisDegnen Great. Feel free to update the code in the answer if you feel this change is important. – Leonid Shifrin – 2013-02-07T14:27:42.560