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
chain() + zip() zip() can be used to link both the lists and then chain() can used to perform the alternate append of the elements as desired. This is the most efficient method to perform this task.
In order to combine (concatenate) two arrays, we find its length stored in aLen and bLen respectively. Then, we create a new integer array result with length aLen + bLen . Now, in order to combine both, we copy each element in both arrays to result by using arraycopy() function.
"Interleaved" means that multiple attributes, possibly of different types, (e.g., position, normal, uv, color) are packed into a single array buffer.
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))]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With