# Can't Extract work with All?

I've got a data structure that consists of a long list of triples; each triple consists of a number, a two-element pair, and a two-element pair. Symbolically, I can represent this data structure as {{t1, {x1, y1}, {vx1, vy1}}, {t2, {x2, y2}, {vx2, vy2}}, ...}.

I want to extract just the tN and yN values as pairs, to end up with a list like this: {{t1, y1}, {t2, y2}, ...}. I can think of several ways to do this, including: pulling the tN out into one variable, the yN out into another, packaging the two together into a list, and transposing; or, flattening and using Part. However, the outermost list is likely to be very long, and I want to minimize list rearrangement and copying.

It seems like Extract should do the job. And it would, too, except that it throws an error whenever I try to use All as a position specification. When I try this:

traj = {{t1, {x1, y1}, {vx1, vy1}}, {t2, {x2, y2}, {vx2, vy2}}, {t3, {x3, y3}, {vx3, vy3}}};
Extract[traj, {{All, 1}, {All, 2, 2}}]


I get a "Position specification… is not applicable" error. The same thing happens if I try the ;; syntax. However, the following work (although they only produce one pair, not the entire list of pairs):

Extract[traj, {{1, 1}, {1, 2, 2}}]
(* ==> {t1, y1} *)

Extract[traj, {{-1, 1}, {-1, 2, 2}}]
(* ==> {t3, y3} *)


The best solution I've come up with so far is:

Extract[traj, {{#, 1}, {#, 2, 2}}] & /@ Range[Length[traj]]


But the question remains: Is there no way to make Extract take All, or something that has the equivalent functionality? I am flabbergasted that Extract differs from Part in this one small but important way.

• What an interesting variety of solutions! I accepted @chuy's because I find it the most transparently readable (especially with infix notation for Map). I admit I haven't done careful timing comparisons yet for performance. – ibeatty Sep 9 '16 at 1:40

Yet another way using the operator form of Extract:

Map[Extract[{{1}, {2, 2}}], traj]
(* {{t1, y1}, {t2, y2}, {t3, y3}} *)


Use destructuring.

helper[{t_, {_, y_}, _}] := {t, y}
helper /@ traj


{{t1, y1}, {t2, y2}, {t3, y3}}

I would approach this with Part (shorthand [[ ]]) rather than Extract:

Thread[{traj[[All, 1]], traj[[All, 2, 2]]}]
{{t1, y1}, {t2, y2}, {t3, y3}}


MapAt is the only function I know that allows a list position to contain All. You could exploit that fact:

Reap[MapAt[Sow, traj, {{All, 1}, {All, 2, 2}}]][[2, 1]]


However, I like the following workaround better:

traj[[Sequence @@ #]] & /@ {{All, 1}, {All, 2, 2}}

• Transpose[traj[[##]] & @@@ {{All, 1}, {All, 2, 2}}] – Alexey Popkov Sep 9 '16 at 2:33