How to thread a list
Another approach using Transpose
:
Transpose[{Table[First@#,{Length@#-1}],Rest@#},{3,1,2}]&@data
(* Out[1]= {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} *)
On my pc, it is about 3 times faster than the Outer/Flatten
approach.
edit:
It seems that the bottleneck is Table
.By changing it into ConstantArray
:
Transpose[{ConstantArray[First@#,Length@#-1],Rest@#},{3,1,2}]&@data
Now it is about 10 times faster than the Outer/Flatten
approach.
If your lists are long, there are faster approaches using high-level functions and structural operations. Here are two alternatives.
First we try Outer
and Flatten
:
data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}};
Flatten[Outer[List, List@First[data], Rest[data], 1], {{2}, {1, 4}}]
{{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}}
And now Distribute
and Transpose
:
Transpose[Distribute[{List@First[data], Rest[data]}, List], {1, 3, 2}]
{{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}}
Evidently, they give the correct result. Now for a Timing
comparison:
data = RandomReal[{0, 1}, {10^6, 2}];
The timings, in rank order, are:
- kptnw's
Table
/Transpose
method: 0.297 seconds Outer
/Flatten
: 0.812 secondsDistribute
/Transpose
: 0.891 seconds- rcollyer's
Thread
/Map
approach: 2.907 seconds - R.M's
Transpose
/FoldList
method: 3.844 seconds - paradox2's solution with
Riffle
andPartition
: 7.407 seconds
The Outer
/Flatten
and Distribute
/Transpose
approaches are quite fast, but clearly Table
is much better-optimized than Distribute
, since while these two methods are conceptually similar, kptnw's solution using the former is by far the fastest and most memory-efficient. The other solutions, not using structural operations, are considerably slower, which is not unexpected.
This works:
data = {{a1,a2}, {b1, b2}, {c1, c2}, {d1, d2}}
With[{fst = First@#, rst = Rest@#}, Thread[{fst, #}] & /@ rst]& @ data
{{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}}