# Non uniform Riffle of two lists

Let's say I have

x = {b1, b2}

and

y = {{a1, a2}, {a3, a4}, {a5, a6}}

I want to produce the riffle'd list

z = {{{b1, a1}, {b2, a2}}, {{b1, a3}, {b2, a4}}, {{b1, a5}, {b2, a6}}}

Attempt

I have produced this horible code

riffle[a_, b_] := Riffle[a, b, {1, -1, 2}]
tt = Reverse /@ MapThread[{#1, #2} &, {x, Transpose@y}, 1];
Partition[#, 2] & /@ Map[riffle @@ ## &, tt, {1}] // Transpose

which does the trick but...

Question

I am fairly certain there should be a simpler method?

Thank you for your help in seeking elegance in mathematica!

• Why isn't Transpose[{{b1, b2}, #}] & /@ {{a1, a2}, {a3, a4}, {a5, a6}} sufficient? – J. M.'s technical difficulties May 13 at 9:19
• @J.M. because you are smart and I am dumb :-). Either write it as an answer or I delete my post? – chris May 13 at 9:24
• I would prefer you answer your own question, if you can explain why it works. ;) – J. M.'s technical difficulties May 13 at 10:37
• @J.M. so now I accept my own (i.e. your's) answer? I feel its a bit cheeky! – chris May 14 at 9:02
• It would be less cheeky if you added an explanation why it works, you know. ;) (However, I cannot give a second upvote.) – J. M.'s technical difficulties May 14 at 9:11

## 3 Answers

x = {b1, b2};
y = {{a1, a2}, {a3, a4}, {a5, a6}};

(As suggested in the comments by user1066)

Inner[{#2, #1}&, y, x, List]

$$\left( \begin{array}{cc} \{\text{b1},\text{a1}\} & \{\text{b2},\text{a2}\} \\ \{\text{b1},\text{a3}\} & \{\text{b2},\text{a4}\} \\ \{\text{b1},\text{a5}\} & \{\text{b2},\text{a6}\} \\ \end{array} \right)$$

My earlier solution:

Inner[Reverse@*List, y, x, List]

Timing comparisons:

i1 = First@RepeatedTiming[ai1 = Inner[{#2, #1} &, y, x, List]];
i2 = First@RepeatedTiming[ai2 = Inner[Reverse@*List, y, x, List]];
t = First@RepeatedTiming[at = Transpose[{x, #}] & /@ y];
{i2, t}/i1

{1.54407, 2.7154}

It gives a 1.5x speed up, and 2.7x compared to using Transpose.

ai1 == ai2 == at

True

• +1 Looks elegant. Would you kindly explain how it works? I find it difficult to follow, even after reading about Inner. – DavidC May 13 at 13:33
• @DavidC First evaluate Inner[f, y, x, g]. Then you can better see why the values of g and f are List and Reverse@*List. – Suba Thomas May 13 at 13:42
• Actually J. M.'s Transpose solution is simpler and better than this. – Suba Thomas May 13 at 13:46
• @David, to put Suba's explanation in another way: think of what happens when you take the usual dot product of a matrix and a vector, and consider what happens if you replace the addition and the multiplication with something else. – J. M.'s technical difficulties May 13 at 13:48
• @user1066 Thanks. That speeds it up a little. And it appears that the Inner solution is faster than that using Transpose. – Suba Thomas May 13 at 17:34

as suggested by @J.M. (who gets all the credit) there is in fact a very simple solution (as I feared! :-) ):

Transpose[{{b1, b2}, #}] & /@ {{a1, a2}, {a3, a4}, {a5, a6}}

Why it works

Well, it seems obvious a posteriori ( :-) ) especially since JM's solution is elegant and simple.

The mapping takes in turn {a1, a2}, {a3, a4} ... and applies {{b1, b2}, #}& to each list so that we have a list of

{{b1, b2},{a1, a2}},  {{b1, b2},{a3, a4}}...

Thanks to the Transpose it becomes

{{b1, a1}, {b2, a2}}, {{b1, a3}, {b2, a4}}...

Hence the result.

Postscript

My own clumsy solution arose because I failed to realise that the length of {b1,b2} was always 2.

• I use this exact same transpose method to take some list of x values and disperse it to a list of lists of different y values! Very cool. – CA Trevillian May 14 at 11:23

How about something like this?

x = {b1, b2};
y = {{a1, a2}, {a3, a4}, {a5, a6}};
z = {{{b1, a1}, {b2, a2}}, {{b1, a3}, {b2, a4}}, {{b1, a5}, {b2,a6}}};
Partition[#, 2] & /@ Riffle @@@ Table[{x, k}, {k, y}]
%==z

{{{b1, a1}, {b2, a2}}, {{b1, a3}, {b2, a4}}, {{b1, a5}, {b2, a6}}}

True

The first step:

t = Table[{x, k}, {k, y}]

{{{b1, b2}, {a1, a2}}, {{b1, b2}, {a3, a4}}, {{b1, b2}, {a5, a6}}}

The second step:

Riffle@@@ t

{{b1, a1, b2, a2}, {b1, a3, b2, a4}, {b1, a5, b2, a6}}

Then all that's needed is to Partition each sublist. For example,

Partition[{{b1, a1, b2, a2},2]

{{b1,a1},{b2,a2}}