# Is there a way to riffle more than two lists?

I thought Riffle would generalize such that

Riffle[{a,b,c},{1,2,3},{x,y,z}]


would return

{a,1,x,b,2,y,c,3,z}


It turns out that's not the case.

What's the easiest way to do a multi-list riffle?

{{a, b, c}, {1, 2, 3}, {x, y, z}} ~Flatten~ {2, 1}


{a, 1, x, b, 2, y, c, 3, z}

• Even better! I didn't know Flatten had this more sophisticated use. Plus, this one properly flattens levels. Sep 5 '14 at 15:16
• @Andrew Worth noting is that despite being a single clean operation this is actually slower than Join @@ Transpose @ lists in most cases. (You still have my vote, Simon.) Sep 5 '14 at 15:25
• @Mr.Wizard - Would you consider adding your variant as a separate answer so people more easily see it as an option? Sep 7 '14 at 2:32
• @Mr.Wizard Seconding Andrew's request. Jul 24 '15 at 4:28
• Believe me, {{a, b, c}, {1, 2, 3}, {x, y, z}} ~Flatten~ {2, 1} is newbie unfriendly, compared to Flatten[{{a, b, c}, {1, 2, 3}, {x, y, z}}, {2, 1}]. Mar 22 '17 at 19:41

Riffle does more than simply interleave lists of equal length. When the lists are not of the same length it will repeat elements from the second list, and it will also leave an element from the first list last position:

Riffle[{a, b, c, d, e, f}, {1, 2, 3}]

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


How this would be generalized to multiple lists is not clear which I suspect is why Riffle permits only two lists as input.

Perhaps you would find use, or at least interest, in the following construct:

multiRiffle[x : _List ..] :=
Module[{i = 1},
Fold[Riffle[##, {++i, -1, i}] &, {x}]
]


Now:

multiRiffle[{a, b, c}, {1, 2, 3}, {x, y, z}]

{a, 1, x, b, 2, y, c, 3, z}


But also:

multiRiffle[{a, b, c, d}, {1, 2}, {x, y, z}]

{a, 1, x, b, 2, y, c, 1, z, d, 2, x}

multiRiffle[{a, b}, {1, 2, 3, 4}, {x}]

{a, 1, x, b, 2, x}


I think these are closer in spirit to Riffle than a simple transpose/flatten operation.

• Ah, that makes sense—so it was I who misunderstood Riffle's generalization. Indeed in my application I assume equal-length lists and so @SimonWoods' solution works; however I appreciate the insight into an actually generalized Riffle. Sep 5 '14 at 15:20
Flatten @ Transpose[{{a, b, c}, {1, 2, 3}, {x, y, z}}]


{a, 1, x, b, 2, y, c, 3, z}

• Ah, of course. Thanks! Sep 5 '14 at 14:40
• For future readers: use Flatten[Transpose[{{a, b, c}, {1, 2, 3}, {x, y, z}}], 1] if your elements are lists themselves, or else they'll be flattened too. Sep 5 '14 at 15:15
• @Andrew That case would also be handled by Join @@ Sep 5 '14 at 15:18

Regarding Simon's Flatten method I commented:

Worth noting is that despite being a single clean operation this is actually slower than Join @@ Transpose @ lists in most cases.

Part of the reason that I "only" commented is that I had not invested the time necessary to back up this claim, and as we will see it is questionable. Here are the two functions I shall be comparing and the test function I shall use:

f1 = # ~Flatten~ {2, 1} &;
f2 = Join @@ (#\[Transpose]) &;

test = Table[First @ RepeatedTiming @ fn[#], {fn, {f1, f2}}] &;


All timings are being performed in version 10.1.0 under Windows x64.

First with packed integers with three different array shapes:

RandomInteger[99, {50000, 5}] // test
RandomInteger[99, {5, 50000}] // test
RandomInteger[99, {500, 500}] // test

{0.00200, 0.00115}

{0.00209, 0.0127}

{0.00205, 0.00164}


So f1 (Flatten) is uniform in speed whereas f2 varies with the shape of the array. In the case where input is only a few very long rows its is significantly slower than f1, but in the other two cases it does pull ahead.

With unpackable data:

RandomChoice[{"a", "b", "c"}, {50000, 5}] // test
RandomChoice[{"a", "b", "c"}, {5, 50000}] // test
RandomChoice[{"a", "b", "c"}, {500, 500}] // test

{0.00788, 0.00558}

{0.00626, 0.00774}

{0.00684, 0.00359}


both functions slow down with the exception of f2 on the long-rows case where it is actually faster (but still slower than f1 on the same data). Timings are fairly similar in the first two cases but with the square matrix f2 is nearly twice as fast.

I conclude that my statement that f2 is faster "in most cases" is dubitable, however f2 is enough faster in some cases that it is still worth knowing.

More genaral approach:

Flatten@Riffle[{a, b, c, d, e, f, g}, Transpose@{{1, 2, 3}, {x, y, z}}]
(*{a, 1, x, b, 2, y, c, 3, z, d, 1, x, e, 2, y, f, 3, z, g}*)

MapThread[Sequence, {{a, b, c}, {1, 2, 3}, {x, y, z}}]


{a, 1, x, b, 2, y, c, 3, z}

Thread[Unevaluated @ Sequence[{a, b, c}, {1, 2, 3}, {x, y, z}]]


{a, 1, x, b, 2, y, c, 3, z}