For large inputs using a binary mask generated with RandomInteger
is faster than posted alternatives:
Clear["Global`*"]
recomb1 = Module[{la = #, lb = #2,
pos = Flatten[SparseArray[RandomInteger[1, Dimensions@#]]["NonzeroPositions"]]},
la[[pos]] = lb[[pos]]; la] &;
recomb2 = Module[{pos = Random`Private`PositionsOf[RandomInteger[1, Length@#], 1],
la = #, lb = #2}, la[[pos]] = lb[[pos]]; la] &;
recomb3 = Module[{, la = Flatten@#, lb = Flatten@#2,
pos = Random`Private`PositionsOf[RandomInteger[1, Times @@ Dimensions[#]], 1]},
la[[pos]] = lb[[pos]]; ArrayReshape[la, Dimensions@#]] &;
recomb4 = Module[{pos = RandomInteger[1, Dimensions@#]}, (1 - pos) # + pos #2] &;
Using l1
and l2
from Bob Hanlon's post:
l1 = CharacterRange["a", "z"] // ToExpression;
l2 = Range[Length[l1]];
SeedRandom[1234]
RepeatedTiming[res1 = recomb1[l1, l2]]
{0.000028, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q, 18,
19, t, 21, v, 23, x, y, z}}
SeedRandom[1234]
RepeatedTiming[res2 = recomb2[l1, l2]]
{0.000019, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q, 18,
19, t, 21, v, 23, x, y, z}}
SeedRandom[1234]
RepeatedTiming[res3 = recomb3[l1, l2]]
{0.0000386, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q,
18, 19, t, 21, v, 23, x, y, z}}
SeedRandom[1234]
RepeatedTiming[res4 = recomb4[l1, l2]]
{0.000031, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q, 18,
19, t, 21, v, 23, x, y, z}}
SeedRandom[1234]
RepeatedTiming[res5 = RandomChoice /@ Thread[{l1, l2}]]
{0.000025, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q, 18,
19, t, 21, v, 23, x, y, z}}
SeedRandom[1234]
RepeatedTiming[res6 = RandomChoice /@ Transpose[{l1, l2}]]
{0.000036, {1, 2, 3, d, e, f, g, h, i, 10, 11, l, 13, n, o, 16, q, 18,
19, t, 21, v, 23, x, y, z}}
Multi-dimensional inputs:
recomb3
and recomb4
can handle multi-dimensional lists:
l1 = ArrayReshape[CharacterRange["a", "z"] // ToExpression, {13, 2}]
{{a, b}, {c, d}, {e, f}, {g, h}, {i, j}, {k, l}, {m, n}, {o, p}, {q,
r}, {s, t}, {u, v}, {w, x}, {y, z}}
l2 = ArrayReshape[Range[Length[l1]], {13, 2}]
{{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, {13, 14}, {15,
16}, {17, 18}, {19, 20}, {21, 22}, {23, 24}, {25, 26}}
SeedRandom[1234]
recomb3[l1, l2]
{{1, 2}, {3, d}, {e, f}, {g, h}, {i, 10}, {11, l}, {13, n}, {o,
16}, {q, 18}, {19, t}, {21, v}, {23, x}, {y, z}}
SeedRandom[1234]
recomb4[l1, l2]
{{1, 2}, {3, d}, {e, f}, {g, h}, {i, 10}, {11, l}, {13, n}, {o,
16}, {q, 18}, {19, t}, {21, v}, {23, x}, {y, z}}
Timings for large inputs:
Symbolic l1
:
n = 1000000;
SeedRandom[1234]
l1 = RandomChoice[CharacterRange["a", "z"] // ToExpression, n];
l2 = Range[Length[l1]];
SeedRandom[1234]
First @ RepeatedTiming[res1 = recomb1[l1, l2];]
0.15
SeedRandom[1234]
First @ RepeatedTiming[res2 = recomb2[l1, l2];]
0.13
SeedRandom[1234]
First@RepeatedTiming[res3 = recomb3[l1, l2];]
0.15
SeedRandom[1234]
First @ RepeatedTiming[res4 = recomb4[l1, l2];]
0.77
SeedRandom[1234]
First @ RepeatedTiming[res5 = RandomChoice /@ Thread[{l1, l2}];]
0.93551
SeedRandom[1234]
First @ RepeatedTiming[res6 = RandomChoice /@ Transpose[{l1, l2}];]
1.11
Integer l1
:
SeedRandom[1234]
n = 1000000;
l1 = n + ArrayComponents @ RandomChoice[CharacterRange["a", "z"] // ToExpression, n];
l2 = Range[Length[l1]];
SeedRandom[1234]
First@RepeatedTiming[res1 = recomb1[l1, l2];]
0.054
SeedRandom[1234]
First@RepeatedTiming[res2 = recomb2[l1, l2];]
0.043
SeedRandom[1234]
First@RepeatedTiming[res3 = recomb3[l1, l2];]
0.050
SeedRandom[1234]
First@RepeatedTiming[res4 = recomb4[l1, l2];]
0.035
SeedRandom[1234]
First@RepeatedTiming[res5 = RandomChoice /@ Thread[{l1, l2}];]
0.53
SeedRandom[1234]
First@RepeatedTiming[res6 = RandomChoice /@ Transpose[{l1, l2}];]
0.205