My first list that has the numbers I want to generate:
list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
My second list (list1
) has how many times each number from my first list needs to be repeated in the final list:
list1 = [45, 38, 18, 18, 41, 14, 40, 42, 3, 26, 12, 23]
The answer I am looking for should have first element of list i.e. '0' repeated equal to first element of list1 i.e. '45' times. Similarly it should have '1' repeated '38' times, '2' repeated 18 times, and so on.
Note that both lists have exactly the same number of elements (i.e. 12). Also, the total number of elements in my final list is equal to the sum of elements in list1
: 320.
What I tried, but did not work:
x = [i for i in range(0, 320)]
for i in range(len(list)):
x = [i for list1[i] in range(0,len(list))]
x.append(x)
Can someone help?
CodePudding user response:
There's a couple of ways to do this.
You could use a nested for
loop:
result = []
for idx in range(len(list1)):
for count in range(list2[idx]):
result.append(list1[idx])
You can simplify this using zip()
and .extend()
:
result = []
for elem, count in zip(list1, list2):
result.extend([elem] * count)
Or, you could even use itertools.chain.from_iterable()
as well as itertools.repeat()
to turn this into a clean one-liner:
from itertools import chain, repeat
result = list(chain.from_iterable(repeat(elem, count) for elem, count in zip(list1, list2)))
Note that I've renamed your lists from list
and list1
to list1
and list2
respectively, as you shouldn't name your variable list
. (It shadows a builtin.)
CodePudding user response:
There are a few issues. First, you are shadowing names:
x = list(range(10))
for item in x:
x = list(range(item))
x.append(x)
What's actually happening here? You are redefining x, so it appends itself at the end of each iteration, then at the start of the next step, x is redefined. So you really just get:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]
I think you got your iteration mixed up. So let's step back. You have two lists, let's call them a
and b
. Since a
represents values and b
represents the count of those values, we can assume that a
and b
have the same length. The initial way you might solve this is with an index:
a, b = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [45, 38, 18, 18, 41, 14, 40, 42, 3, 26, 12, 23]
final = []
for i in range(len(a)):
x, y = a[i], b[i]
# append x y times to final
for i in range(y):
final.append(x)
This way, we aren't shadowing names, and we are appending to the final result. However, there's a better way. With zip
we can iterate through corresponding elements:
for x, y in zip(a, b):
for i in range(y):
final.append(x)
However, the best way might be to use list.extend
:
for x, y in zip(a, b):
final.extend([x for _ in range(y)])
CodePudding user response:
This should do the trick for you. You could also use multiple as shown in the answers above.
li1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
li2 = [45, 38, 18, 18, 41, 14, 40, 42, 3, 26, 12, 23]
result = [n for n, m in zip(li1, li2) for _ in range(m)]
Note:
You should never name a list
list as that's a reserved word in Python, yet it can be overwritten.
CodePudding user response:
I know there are native ways to do this, but I'd choose use numpy instead:
# Get data
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
times = [45, 38, 18, 18, 41, 14, 40, 42, 3, 26, 12, 23]
# Import numpy and use repeat function
from numpy import repeat
# First way: Get list of arrays
result = [repeat(n,t) for n,t in zip(numbers, times)]
# Second way: Get single list
l = []
for (n,t) in zip(numbers, times):
for el in repeat(n,t):
l.append(el)
CodePudding user response:
Assuming the two lists are always in 1-1 correspondence then you can zip
them to make pairs of the form value-counter. To flat the list you can use, for example, sum(... , [])
, see doc.
Remark: as suggested in the doc, the preferred way to concatenate iterable is itertools.chain
list, list1 = # see question
flat = sum([[i]* counter for i, counter in zip(list, list1)], [])
print(flat)