14
$\begingroup$

Say I have a list with the structure

list = {{1, {x1, y1, z1}}, {2, {x2, y2, z2}}, {3, {x3, y3, z3}}, ...}

I would like to slice it such that I end up with

{{1, y1}, {2, y2}, ...}

Is there a clean way to do this with Part? Ie, something along the lines of

list[[All, {1,{2,2}}]]

(which clearly isn't the right levelspec syntax). But, for the life of me, I can't figure out how to slice it properly.

I know this is ultimately possible doing something like

Map[{#[[1]], #[[2, 2]]} &, list]

but this is a bit clumsy and I'm hoping there is a straight-forward list slice I can use instead. Not to mention, I clearly don't fully get how Mathematica implements Part, and I keep running around in circles on the help page.

$\endgroup$
11
$\begingroup$
list = {{1, {x1, y1, z1}}, {2, {x2, y2, z2}}, {3, {x3, y3, z3}}};

In addition to your current method

{#[[1]], #[[2, 2]]} & /@ list 

You can use a number of additional methods, including

Transpose[{list[[All, 1]], list[[All, 2, 2]]}]
{#, #2[[2]]} & @@@ list
{#, #2 & @@ #2} & @@@ list
Transpose@Extract[Transpose[list], {{1}, {2, All, 2}}]
list2 = list; list2[[All, 2]] = list2[[All, 2, 2]]; list2
(* or, more simply, list[[All,2]]=list[[All,2,2]] if you want to modify the list *)
list3 = list; list3[[All, 2, 0]] = #2 &; list3

to get

{{1, y1}, {2, y2}, {3, y3}}
$\endgroup$
  • $\begingroup$ Thanks! So I take it there isn't a way to get that slice just using Part? $\endgroup$ – Neal Pisenti Nov 14 '14 at 13:30
  • $\begingroup$ @Neal, afaik not as of v10 :) Maybe someone more knowledgable could suggest a way to overload Part to accept an argument pattern like {1,{2,2}} (which, btw, is very natural, also the pattern i thought should work). $\endgroup$ – kglr Nov 14 '14 at 13:55
  • $\begingroup$ I just wanted to clarify in the event you are brand new to Mathematica- in my mind, the first method kgular illustrated is pretty much only using part. The shorthand notation for part is [[x]]. It is true that technically, he is also using list {} and map /@ to get your desired solution, but this is a very typical way of doing list manipulation in Mathematica. I don't see Wolfram ever adding on to the Part function so that you only have to use part in place of the aforementioned method. @kguler, +1 for the answer! $\endgroup$ – tjm167us Nov 14 '14 at 14:06
5
$\begingroup$

I find extracting the parts and then combining them (e.g. with Transpose) to be fast and general. kguler already showed this but again for reference:

{list[[All, 1]], list[[All, 2, 2]]}\[Transpose]
{{1, y1}, {2, y2}, {3, y3}}

Pattern matching is another general method, though often not quite as fast.

Cases[list, {a_, b_} :> {a, b[[2]]}]
{{1, y1}, {2, y2}, {3, y3}}

Since your example only requires modification of the {x1, y1, z1} part you could also use MapAt:

MapAt[#[[2]] &, list, {All, 2}]
{{1, y1}, {2, y2}, {3, y3}}
$\endgroup$
4
$\begingroup$

Using Replace

list /. {a_, b_List} :> {a, b[[2]]}

or

Replace[list, a_List :> a[[2]], {2}]

{{1, y1}, {2, y2}, {3, y3}}

$\endgroup$
3
$\begingroup$

Mapping Thread on the list is useful in a lot of such cases:

(Thread /@ list)[[All, 2]]

(* {{1, y1}, {2, y2}, {3, y3}} *)
$\endgroup$
2
$\begingroup$

Another method

list // Thread[{#[[All, 1]], #[[All, 2, 2]]}] &

{{1, y1}, {2, y2}, {3, y3}}

$\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.