# Looking for an elegant way to construct this tensor-product-ish list

I would like to make the following matrix:

{
{{1, 13}, {1, 14}, {1, 15}, {1, 16}, {2, 13}, {2, 14}, {2, 15},{2, 16}, ...,
{32, 13}, {32, 14}, {32, 15}, {32, 16}},
{{1, 9}, {1, 10}, {1, 11}, {1, 12}, {2, 9}, {2, 10}, {2, 11}, {2, 12}, ...,
{32, 9}, {32, 10}, {32, 11}, {32, 12}},
...
{{1, 1}, {1, 2}, {1, 3}, {1, 4}, {2, 1}, {2, 2}, {2, 3},{2, 4}, ...,
{32, 1}, {32, 2}, {32, 3}, {32, 4}}
}


I'd like to make this out of these two things:

A = {Range[13, 16], Range[9, 12], Range[5, 8], Range[4]}


and

B = Range[32]


In other words, I'd like to glue copies of A all in a row with each entry indexed by B.

Is there a good way to do this?

-

You could do this:

Outer[List, B, #] & /@ A

-
+1! Clear and elegant – Jagra Jun 26 '13 at 19:21
This is very nice. I should add that it does fall slightly short of my desired form, but the gap can be easily closed by Flatten[#,1]&/@(Outer[List,B,#]&/@A). – Alexander Gruber Jun 26 '13 at 23:11
@AlexanderGruber I like this one a little better: Flatten[Outer[List, B, A], {{2}, {1, 3}, {4}}] – Oleksandr R. Jun 26 '13 at 23:35
@OleksandrR. Yes, those mysterious arguments of Flatten are cool if you get them to work. But I honestly would have chosen Alexander's approach (if I had noticed the different nesting depth in the first place)... One could also do this with Transpose, I think. – Jens Jun 27 '13 at 0:36
Yes, yours is equivalent to Transpose@Outer[List, B, A]. Since Transpose is equivalent to Transpose[..., {2, 1}] and Flatten[..., {{2}, {1}}], and given that he wanted to flatten the two middle levels together, that got me from yours to what I posted above. Actually, it can be written as Flatten[Outer[List, B, A], {{2}, {1, 3}}], although the fact that trailing unaltered levels can freely be omitted from the second argument doesn't seem to be documented. – Oleksandr R. Jun 27 '13 at 0:48

Another possibility is Distribute

soln = Distribute[{B, #}, List] & /@ A


And

soln == (Flatten[#, 1] & /@ (Outer[List, B, #] & /@ A)) ==
Flatten[Outer[List, B, A], {{2}, {1, 3}, {4}}]


=> True

Edit

Yet another possibility is Tuples

(A little surprising to my mind that this one works)

Tuples[{B, #}] & /@ A


And

(Tuples[{B, #}] & /@ A) == soln


=> True

-
Very nice (+1). – Jens Jun 27 '13 at 0:38
Tuples clearly seems the best way to go; it's also an order of magnitude faster than other options on most data. You should IMHO add timings to your answer in support of the superiority of your last method; if you don't have time I can do it if you'd like. – Mr.Wizard Aug 7 '13 at 9:40
@Mr.Wizard. No time at the moment but by all means add/edit anything you want. Thanks. – user 106 Aug 7 '13 at 11:30

This is not at all elegant as @Jens but this is one more long way to do it. First we establish interaction between both lists as,

Table[{B[[k]], A[[i, j]]}, {i, 1, Length[A]}, {j, 1,
Length[A[[i]]]}, {k, 1, Length[B]}]


After that we flatten the array as,

arr = ArrayFlatten[%]


Than again partition the sublists using Table as,

Table[Partition[arr[[i]], 2], {i, 1, Length[arr]}]