问题
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
zipthexandyso that the element fromxand its corresponding count fromyare grouped as a single tuple. Then, we iteratecountnumber of items to produce the same item.If your objects in
xare immutables, then you can createcountcopies 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
chainreturns 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 thecountis 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
repeatoverxandyand get the result like this>>> list(chain.from_iterable(map(repeat, x, y))) [2, 3, 3, 4, 4, 4]here,
mapfunction will apply the values fromxandytorepeatone by one. So, the result ofmapwill be>>> list(map(repeat, x, y)) [repeat(2, 1), repeat(3, 2), repeat(4, 3)]Now, we use
chain.from_iterableto 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