# Reshaping nested list

I have the feeling this is a very basic question, but I can't seem to find the way to solve this easily.

I have imported a set of data from a txt file into a table so the resulting list has the following structure:

{{x1,y1,f1},{x2,y2,f2},...}


I want it to reshape it into this form:

{{{x1,y1},f1},{{x2,y2},f2},...}


I apologize because I know it must be trivial but I haven't found the way yet. I've always had problems manipulating lists in Mathematica so, if anyone has any resource I can use to learn about this it'd be very much appreciated.

Regards

• Look at the output for Apply[{{#1, #2}, #3} &, {a, b, c}] and it should help you. Check Apply for more details. – Jason B. Feb 4 '19 at 22:27
• Also possible is the following: reshape = Curry[Replace, {3, 1, 2}][{s_, t_, u_} :> {{s, t}, u}, {1}]. Then {{x1, y1, f1}, {x2, y2, f2}} // reshape gives the desired result. – Shredderroy Feb 4 '19 at 23:53
• @JasonB. this should be Apply[{{#1, #2}, #3} &, {{x1, y1, f1}, {x2, y2, f2}}, {1}] – GenericAccountName Feb 5 '19 at 0:47

I think my vote is this so far, but I bet there's even cleaner/more clever ways to do this:

data = {{x1, y1, f1}, {x2, y2, f2}}
Replace[data, {x_, y_, f_} :> {{x, y}, f}, {1}]


I like the Apply solution just fine too:

Apply[{{#1, #2}, #3} &, {{x1, y1, f1}, {x2, y2, f2}}, {1}]


For larger data they perform similarly, with Replace winning slightly:

In[53]:= data=(ToExpression/@{"x"<>#,"y"<>#,"f"<>#})&/@(ToString[#]&/@Range[1000000]);
Apply[{{#1,#2},#3}&,data,{1}]//RepeatedTiming//First
Replace[data,{x_,y_,f_}:>{{x,y},f},{1}]//RepeatedTiming//First
Out[54]= 0.825
Out[55]= 0.740


This is much better than the most naive approach:

In[57]:= ({{#[[1]], #[[2]]}, #[[3]]} & /@ data) //
RepeatedTiming // First

Out[57]= 1.859


The solution from @Oppenede is similar in timing to Apply

In[77]:= Transpose[{Drop[data, 0, -1], data[[All, -1]]}] // RepeatedTiming // First

Out[77]= 0.836

list = {{x1, y1, f1}, {x2, y2, f2}};

Transpose[{Drop[list, 0, -1], list[[All, -1]]}]
(* {{{x1, y1}, f1}, {{x2, y2}, f2}} *)


Use a rule and replacement:

{{x1, y1, f1}, {x2, y2, f2}} /. {x_, y_, f_} -> {{x, y}, f}

(* {{{x1,y1},f1},{{x2,y2},f2}} *)

• Thank you. This works well and I feel it could be useful as an example for other cases. – Mikel García Feb 5 '19 at 6:04
• You’re welcome, Mikel. Using Replace with a rule based on a pattern, like this, is often less efficient than mapping an anonymous function. But I find it so clear and understandable that I often use it when execution time is not an issue. – David Keith Feb 5 '19 at 6:10
• It is better to use Replace with a level spec as this tests each expression at each level – GenericAccountName Feb 5 '19 at 15:37
list = {{x1, y1, f1}, {x2, y2, f2}};

{Most[#], Last[#]} & /@ list

(* {{{x1, y1}, f1}, {{x2, y2}, f2}} *)

• This is a bit slower than the replace solutions and simliar to {{#[[1]], #[[2]]}, #[[3]]} & /@ data – GenericAccountName Feb 5 '19 at 20:17
• @GenericAccountName Yes, it is. My personal preference is to avoid using [[]] as I find it quite visually jarring. – Rohit Namjoshi Feb 5 '19 at 21:25
• I agree, I prefer your syntax as well for this, the main point of my comment is this is a slower solution than others. – GenericAccountName Feb 5 '19 at 22:08