5
$\begingroup$

Consider the below list

testlist = {0, 1, 2, 0, 0, 1, "a", "b", "c", "d", "e", "f"}

I am trying to group every two numbers and every two letters in a list, and in the end form the following result:

reslist={{0, 1, a, b},{2, 0, c, d}, {0, 1, e, f}}

What I do is the following:

testmp= Partition[testlist, 2];
reslist = {};
 For[ii = 1, ii <= Length[testmp]/2, ii++,
  AppendTo[reslist, {testmp[[ii]], testmp[[ii + Length[testmp]/2]]}]
  ];

Q: Is there simple way to do it? Furthermore, when the testlist is described by CombineList and gets larger, how one can efficiently do it? I find some links which potentially works but I failed to use it.

value = {{0, 1, 2, 0, 0, 1}, {0, 1, 2, 0, 0, 2}, {0, 1, 2, 0, 1, 0}, {0, 1, 2, 0, 1, 1}};
label = {{"a", "b", "c", "d", "e", "f"}, {"a", "b", "d", "f", "c", "e"}};
CombineList = Array[Join[value[[#2]], label[[#]]] &, Length /@ {label, value}]

one example:

testlist={{0, 1, 2, 0, 0, 1, "a", "b", "c", "d", "e", "f"}, {0, 1, 2, 0, 0, 1, 
  "a", "b", "d", "f", "c", "e"}}

the result could be something like the following

{ {{0, 1, a, b},{2, 0, c, d}, {0, 1, e, f}}, {{0, 1, a, b},{2, 0, d, f}, {0, 1, c, e}} }

Thank you!

$\endgroup$
4
  • 3
    $\begingroup$ This function will do what you need, for your testlist at least: Flatten[TakeDrop[#, Length[#]/2] & @Partition[#, 2], {{2}, {1, 3}}] &. You use it as e.g. Flatten[TakeDrop[#, Length[#]/2] & @Partition[#, 2], {{2}, {1, 3}}] & @ testlist. $\endgroup$ – Leonid Shifrin May 25 at 16:05
  • $\begingroup$ @LeonidShifrin, thank you! that's a good solution for simple lists. does it also work for nested list? Or one have to do some for-loop things? $\endgroup$ – Xuemei May 25 at 16:12
  • 1
    $\begingroup$ Simply Map[function-above, your-nested-list]. $\endgroup$ – Leonid Shifrin May 25 at 16:45
  • $\begingroup$ thank you so much! that helps a lot!@LeonidShifrin $\endgroup$ – Xuemei May 25 at 16:46
5
$\begingroup$
testlist = {{0, 1, 2, 0, 0, 1, "a", "b", "c", "d", "e", "f"}, 
  {0, 1, 2, 0, 0, 1, "a", "b", "d", "f", "c", "e"}}

reShape1 = Join[##, 2] & @@ ArrayReshape[#, {2, 3, 2}] &;

Map[reShape1] @  testlist
 {{{0, 1, "a", "b"}, {2, 0, "c", "d"}, {0, 1, "e", "f"}},
  {{0, 1, "a", "b"}, {2, 0, "d", "f"}, {0, 1, "c", "e"}}}

Also

reShape2 = Join @@@ Transpose @ ArrayReshape[#, {2, 3, 2}] &;
reShape3 = Flatten[ArrayReshape[#, {2, 3, 2}], {{2}, {1, 3}}] &;
reShape4 = ArrayReshape[Transpose @ ArrayReshape[#, {2, 3, 2}], {3, 4}] &;
reShape5 = Transpose @ Fold[Transpose @* ArrayReshape, #, {{2, 3, 2}, {3, 4}}] &;

Equal @@ (Map[#] @ testlist & /@ 
  {reShape1, reShape2, reShape3, reShape4, reShape4})
 True
$\endgroup$
3
  • $\begingroup$ This is a comment regarding the first suggestion you made. I am getting an error when I run the commands. If I use instead reShape1@testlist it gives the desired output $\endgroup$ – DiSp0sablE_H3r0 May 27 at 12:07
  • 1
    $\begingroup$ Thank you @DiSp0sablE_H3r0. I used OP's second input list (also named testlist). $\endgroup$ – kglr May 27 at 12:14
  • 1
    $\begingroup$ Thanks for clarifying and updating the answers. Excellent answer as always btw! +1 from me $\endgroup$ – DiSp0sablE_H3r0 May 27 at 12:16
3
$\begingroup$

Here's a way that generalizes to lists of arbitrary length, provided that they are well-formed (with an even number of integer and string elements, and the same number of integer and string elements):

Catenate /@ 
 Transpose[
  SequenceCases[testlist, {Blank@#, Blank@#}] & /@ {Integer, String}],
(* {{0, 1, "a", "b"}, {2, 0, "c", "d"}, {0, 1, "e", "f"}} *)
$\endgroup$
1
  • $\begingroup$ nice way to create binary files, thank you! $\endgroup$ – Xuemei May 27 at 16:39

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.