salil - 1 year ago 63

Python Question

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

Answer Source

**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.

**original answer below:**

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))]
```