salil - 1 year ago 86
Python Question

# Randomly Interleave 2 Arrays In Python

Suppose I have two arrays:

``````a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]
``````

I want to interleave these two arrays to a variable 'c' (note 'a' and 'b' aren't necessarily of equal length) but I don't want them interleaved in a deterministic way. In short, it isn't enough to just zip these two arrays. I don't want:

``````c = [1, 5, 2, 6, 3, 7, 4, 8, 9]
``````

Instead, I want something random like:

``````c = [5, 6, 1, 7, 2, 3, 8, 4, 9]
``````

Also notice that the order of 'a' and 'b' are preserved in the resulting array, 'c'.

The current solution I have requires a for loop and some random number generation. I don't like it and I'm hoping someone can point me to a better solution.

``````# resulting array
c = []

# this tells us the ratio of elements to place in c. if there are more elements
# in 'a' this ratio will be larger and as we iterate over elements, we will place
# more elements from 'a' into 'c'.
ratio = float(len(a)) / float(len(a) + len(b))

while a and b:
which_list = random.random()
if which_list < ratio:
c.append(a.pop(0))
else:
c.append(b.pop(0))

# tack on any extra elements to the end
if a:
c += a
elif b:
c += b
``````

edit: I think this recent one is best:

``````a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]
c = [x.pop(0) for x in random.sample([a]*len(a) + [b]*len(b), len(a)+len(b))]
``````

Or more efficiently:

``````c = map(next, random.sample([iter(a)]*len(a) + [iter(b)]*len(b), len(a)+len(b)))
``````

Note that the first method above modifies the original lists (as your code did) while the second method does not. On Python 3.x you would need to do `list(map(...))` since `map` returns an iterator.

Here is an option that saves a few lines:

``````a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]

c = []
tmp = [a]*len(a) + [b]*len(b)
while a and b:
c.append(random.choice(tmp).pop(0))

c += a + b
``````

Here is another option, but it will only work if you know that all of your elements are not falsy (no `0`, `''`, `None`, `False`, or empty sequences):

``````a = [1, 2, 3, 4]
b = [5, 6, 7, 8, 9]

ratio = float(len(a)) / float(len(a) + len(b))
c = [(not a and b.pop(0)) or (not b and a.pop(0)) or
(random.random() < ratio and b.pop(0)) or a.pop(0)
for _ in range(len(a) + len(b))]
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download