Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
    
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 at 22:13
3  
New in 3 | Last modified in 8 | Documentation last modified in 5 :-) –  Simon Woods Apr 17 at 14:32

3 Answers 3

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[]

Old answer

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*)

Extract reduces overhead

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
share|improve this answer
    
Now I will feel bad using Part for pure extraction :( but I probably will do that still because of the syntax ;) –  Kuba Apr 17 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 at 15:46
    
@Kuba see the new last section :P –  Jacob Akkerboom Apr 17 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 at 15:52
    
Neat analysis! +1 –  rasher Apr 17 at 21:18

Verified to work in Mathematica V9.0.1 on MS Windows.

share|improve this answer
3  
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}} ... –  kguler Apr 16 at 23:13

It works in Mathematica 8.0.4 under Windows.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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