11

I have a list:

a = {{1, 2, 3, 4, 1, 2, 3, 4}, {5, 6, 7, 8, 5, 6, 7, 8}};

Using Partition and Map I get:

Partition[#, 4]& /@ a
{{{1, 2, 3, 4}, {1, 2, 3, 4}}, {{5, 6, 7, 8}, {5, 6, 7, 8}}}

And now, I would like to get a list which looks like:

 {{{{1, 2},{3, 4}}, {{1, 2},{3, 4}}}, {{{5, 6},{7, 8}}, {{5, 6},{7, 8}}}}

I tried to play around with Partition and Map, but I did not manage to create such a list. Of course there are easy ways to do it using Do loops and AppendTo, but I very much need to avoid Do loops. Does anybody see the way to create the list?

István Zachar
  • 47,032
  • 20
  • 143
  • 291
Mencia
  • 1,324
  • 12
  • 26

8 Answers8

20

There is a new function in Mathematica 9 - ArrayReshape:

ArrayReshape[a, {2, 2, 2, 2}]
{{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}}, {{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}
rcollyer
  • 33,976
  • 7
  • 92
  • 191
Artes
  • 57,212
  • 12
  • 157
  • 245
  • 2
    I am copying from the help... A function based on Partition equivalent to ArrayReshape without padding: pareshape[list_, dims_] := Fold[Partition, Flatten[list], dims[[-1 ;; 2 ;; -1]]] – tchronis Dec 10 '13 at 09:24
11

If you don't have Mathematica 9, this does the same thing as ArrayReshape as shown by Artes.

InverseFlatten[l_,dimensions_]:=Fold[Partition,Flatten@l,Most[Reverse[dimensions]]];
a = {{1, 2, 3, 4, 1, 2, 3, 4}, {5, 6, 7, 8, 5, 6, 7, 8}};
InverseFlatten[a, {2, 2, 2, 2}]
{{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}}, {{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}
faysou
  • 10,999
  • 3
  • 50
  • 125
  • +1. I have been using exactly this code in a number of cases where I needed this functionality. – Leonid Shifrin Dec 09 '13 at 17:22
  • Very nice (+1), but no need for Partition[#1,#2]& when merely Partition will do. – Mr.Wizard Dec 09 '13 at 18:25
  • 1
    True I'll change this. Credit to Michael Pilat for this code http://stackoverflow.com/a/3808284/884752 – faysou Dec 09 '13 at 23:19
  • @Leonid yes this can be useful to write code that works independently of the dimension of a list (so on a flattened list), and then using such function before the part of the code that needs the input to have a given dimension. – faysou Dec 09 '13 at 23:24
  • Edited at the source. Even the best make that mistake it seems. – Mr.Wizard Dec 13 '13 at 22:37
9

Artes' approach looks great. Here's another possibility:

Nest[Partition[#, 2] &, #, 2] & /@ a

{{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}}, {{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}

DavidC
  • 16,724
  • 1
  • 42
  • 94
8

A general recursive formula:

a = {{1, 2, 3, 4, 1, 2, 3, 4}, {5, 6, 7, 8, 5, 6, 7, 8}};

f[x_Integer | {x_}] := x;
f[x_List] := f /@ Partition[x, Length@x/2];

f /@ a
  {{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}}, {{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}
István Zachar
  • 47,032
  • 20
  • 143
  • 291
4

This isn't as much showing you a good way to achieve your goal as it is to show how Map can be applied to parts of a list at different levels (since you said you weren't able to get Map and Partition to do what you wanted):

So continuing from your step:

aa = Partition[#, 4] & /@ a

which is shorthand for Map[Partition[#, 4] &, a] which is equivalent to Map[Partition[#, 4] &, a, {1}], where the {1} is the level specification of where you want Mapto act.

If you now did:

aaa = Map[Partition[#, 2] &, aa, {2}]

you would get your desired result.

Again, Artes and others have shown betters ways of doing your task, but I thought this was a good place to mention this option in Map. For more info, take a look at the documentation for Map, which (on Mathematica 9, at least) also has a link to the tutorial "Applying Functions to Parts of Expressions".

Aky
  • 2,719
  • 12
  • 19
4

Late to the party and drawing on other answers, but I rather like this:

Fold[Partition, #, {2, 2}] & /@ a

This is essentially the same as Faysal's answer but specific to this question. It is also very similar to what I proposed for Reshape vectors exactly like in MATLAB and not unlike my code for Combination and Permutation so I feel justified in posting it.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
3
Partition[#, 2] &  /@ (Partition[#, 2] & /@ a)

{{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}}, {{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}

andre314
  • 18,474
  • 1
  • 36
  • 69
2
Partition[#, 4, 4, None, {}, Partition[{##}, 2] &] & /@ a

{{{{1, 2}, {3, 4}}, {{1, 2}, {3, 4}}},
{{{5, 6}, {7, 8}}, {{5, 6}, {7, 8}}}}

kglr
  • 394,356
  • 18
  • 477
  • 896