Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

3 Answers 3

up vote 13 down vote accepted

You could do this:

Outer[List, B, #] & /@ A
share|improve this answer
1  
+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
1  
@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

share|improve this answer
1  
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. –  TomD 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]}]

This shall answer your question as well probly.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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