# Undocumented form for Extract

Prompted by a comments conversation here, here's an interesting (and often performance enhancing) use of Extract:

target = Join[Range[100], {{1, 2, 3, Range[20]}}];

Rest@Extract[target, {{{}}, {2 ;; 10 ;; 2}, {-1, -1, 1 ;; -1 ;; 2}}]

(* {{2, 4, 6, 8, 10}, {1, 3, 5, 7, 9, 11, 13, 15, 17, 19}} *)


Prepending the {{}} to the extraction list appears to suppress the error message one would otherwise get attempting to use Span, and it appears that most any valid position/span construct can be used in the extraction list.

The extracted list has an empty list as first element (hence the use of Rest). Prepending just {} makes the first element the original list.

I've often found this useful instead of mapping over a list of spans (and faster).

This seems similar to the undocumented extension to MapAt

As noted by Mr. Wizard, this does not appear to work in V7, I'm curious what versions it works in.

-
Verified to work in Mathematica V9.0.1 on MS Windows. – ciao Apr 16 '14 at 22:04
Sorry, I missed your comment until after you posted this. This structure is OK, but personally I would have used something like: "Is it possible to use Span in Extract?" -- "Yes, since at least v9 there is an undocumented syntax for this, and it performs very well..." You can rewrite your Q&A like that if you wish, or leave it as it is; either way it gets the information out to people. +1 :-) – Mr.Wizard Apr 16 '14 at 22:13
Great find (+1). It looks like extraction list could be prepended with anything that does not trigger an error message: {{}}, or {0} or {{101,4,3}} ... – kglr Apr 16 '14 at 23:13
New in 3 | Last modified in 8 | Documentation last modified in 5 :-) – Simon Woods Apr 17 '14 at 14:32
The question example does not work in either 10.0.2 or 10.1.0 under Windows. In both versions the function is returned unevaluated and issues a message. – Mr.Wizard May 12 '15 at 10:23

## Update

I think this behaviour was unintentional. It seems to have been fixed in V10.0.1.

Evidence that it is unintentional

The following command crashed the kernel in V9 (and I think V10.0.0)

Extract[1, {{}, All}]


and printed a funky message too (in V9). Anyway, it makes sense that we should put another pair of brackets around All. Then, this was also weird:

Extract[1, {{}, {All}}]


which used to give Integer[]

One thing to point out is that we can still use the third argument of Extract if we use Span. Indeed Extract is now more general/flexible than Part, except that you cannot use Extract with Set. Extract appears to work quickly on packedarrays.

Timings

Here are some timing comparisons. Extract can indeed beat Part with Map (or like in this answer, Apply), as mentioned by rasher in comments. The result here will be a ragged array, so that we cannot suffice with a single call to Part. Let

max=5*^6;
kk=1000;
mm=max/kk;
target = ConstantArray[Range[kk], mm]; ;


We have

PackedArrayQ[target]

True


If we also let

partSpans = Table[{ii, 1 ;; Mod[ii, kk, 1]}, {ii, 1, mm}]; ;
spans = Prepend[properSpans, {{}}];


Then

(out = Rest@Extract[target, spans]) // Timing // First
(pOut = Part[target, ##] & @@@ partSpans) // Timing // First
pOut === out

0.016991
0.020719
True


More and smaller sublists

For

max = 5*^6;
kk = 5;
mm = max/kk;


The timings become

0.673268 (*Extract*)
1.636892 (*Part*)


It turns out that the difference in timing between the solutions with Extract and Part is mainly due to overhead that is caused by Apply. Another solution shows that the time taken by Part is about the same as that taken by Extract, even in this last case. For the timings below, I use the same parameters as in the last case above.

First we do all the overhead

(pCode =
Apply[
Part,
Hold@Evaluate@Array[Join[{target}, partSpans[[#]]] &, mm],
{2}
]) // Timing // First

5.176928


Then Part is quite quick

(p2Out = ReleaseHold[pCode]) // Timing // First
p2Out === out === pOut

0.902468 (*Extract took 0.673268 *)
True


Possibly temporary note

This is a cleaner way to define pCode (without the wrapper Hold, but using a "delayed definition" instead). Syntax smyntax!

ReleaseHold@
Hold[SetDelayed][
Hold@pCode,
Apply[
Part,
Hold@Evaluate@Array[Join[{target}, partSpans[[#]]] &, mm],
{2}
]
] // Timing // First

-
Now I will feel bad using Part for pure extraction :( but I probably will do that still because of the syntax ;) – Kuba Apr 17 '14 at 15:36
@Kuba Extract is more general and can be faster, but if you can use one call to Part, Part must be faster :). Hm I don't know about syntax arguments :P. I hope in version 10 we get even more control over such things (and we can decide for ourselves whether we like the notation for Composition or not :P) :). – Jacob Akkerboom Apr 17 '14 at 15:46
@Kuba see the new last section :P – Jacob Akkerboom Apr 17 '14 at 15:48
Part has [[ ]] :) and you can e.g. matrix[[;;,1]]=1. :) Composition can be tricky if you need to extract only tiny part but put that operation inside instead of directly on argument. – Kuba Apr 17 '14 at 15:52
Neat analysis! +1 – ciao Apr 17 '14 at 21:18