11
$\begingroup$

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?

$\endgroup$
0

3 Answers 3

13
$\begingroup$

You could do this:

Outer[List, B, #] & /@ A
$\endgroup$
4
  • $\begingroup$ 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). $\endgroup$ Jun 26, 2013 at 23:11
  • 1
    $\begingroup$ @AlexanderGruber I like this one a little better: Flatten[Outer[List, B, A], {{2}, {1, 3}, {4}}] $\endgroup$ Jun 26, 2013 at 23:35
  • 1
    $\begingroup$ @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. $\endgroup$
    – Jens
    Jun 27, 2013 at 0:36
  • $\begingroup$ 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. $\endgroup$ Jun 27, 2013 at 0:48
9
$\begingroup$

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

$\endgroup$
3
  • 1
    $\begingroup$ Very nice (+1). $\endgroup$
    – Jens
    Jun 27, 2013 at 0:38
  • 1
    $\begingroup$ 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. $\endgroup$
    – Mr.Wizard
    Aug 7, 2013 at 9:40
  • $\begingroup$ @Mr.Wizard. No time at the moment but by all means add/edit anything you want. Thanks. $\endgroup$
    – user1066
    Aug 7, 2013 at 11:30
3
$\begingroup$

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]}]

This shall answer your question as well probly.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.