问题
I have two lists, x
and y
:
>>> x = [2, 3, 4]
>>> y = [1, 2, 3]
I want to use these to create a new list. The new list will have each element in x
repeated the number of times specified by the corresponding element in y
. Hence, the desired output is
>>> new_list
[2, 3, 3, 4, 4, 4]
The order of the elements in new_list
doesn't matter to me. It's also not crucial that it be a list
-- any sequence type is fine.
What is the fastest, most efficient, most Pythonic way to achieve this?
回答1:
You can use list comprehension, like this
>>> x = [2, 3, 4] >>> y = [1, 2, 3] >>> [item for item, count in zip(x, y) for i in range(count)] [2, 3, 3, 4, 4, 4]
Here, we
zip
thex
andy
so that the element fromx
and its corresponding count fromy
are grouped as a single tuple. Then, we iteratecount
number of items to produce the same item.If your objects in
x
are immutables, then you can createcount
copies of the same and put them together in a list, like this>>> [i for item, count in zip(x, y) for i in [item] * count] [2, 3, 3, 4, 4, 4]
You can do the same lazily, with itertools.repeat, like this
>>> from itertools import chain, repeat >>> chain.from_iterable((repeat(item, count) for item, count in zip(x,y))) <itertools.chain object at 0x7fabe40b5320> >>> list(chain.from_iterable((repeat(item, cnt) for item, cnt in zip(x,y)))) [2, 3, 3, 4, 4, 4]
Please note that the
chain
returns an iterable, not a list. So, if you don't want all the elements at once, you can get the items one by one from it. This will be highly memory efficient if thecount
is going to be a very big number, as we don't create the entire list in the memory immediately. We generate the values on-demand.Thanks ShadowRanger. You can actually apply
repeat
overx
andy
and get the result like this>>> list(chain.from_iterable(map(repeat, x, y))) [2, 3, 3, 4, 4, 4]
here,
map
function will apply the values fromx
andy
torepeat
one by one. So, the result ofmap
will be>>> list(map(repeat, x, y)) [repeat(2, 1), repeat(3, 2), repeat(4, 3)]
Now, we use
chain.from_iterable
to consume values from each and every iterable from the iterable returned bymap
.
回答2:
numpy's repeat
function gets the job done:
>>> import numpy as np
>>> x = [2, 3, 4]
>>> y = [1, 2, 3]
>>> np.repeat(x, y)
array([2, 3, 3, 4, 4, 4])
回答3:
Simple using for
loop.
>>> x = [2, 3, 4]
>>> y = [1, 2, 3]
>>> final = []
>>> for index, item in enumerate(y):
final.extend([x[index]]*item)
回答4:
One way to achieve this is via using .elements() function of collections.Counter() along with zip. For example:
>>> from collections import Counter
>>> x = [2, 3, 4]
>>> y = [1, 2, 3]
# `.elements()` returns an object of `itertool.chain` type, which is an iterator.
# in order to display it's content, here type-casting it to `list`
>>> list(Counter(dict(zip(x,y))).elements())
[2, 3, 3, 4, 4, 4]
来源:https://stackoverflow.com/questions/33382474/repeat-each-item-in-a-list-a-number-of-times-specified-in-another-list