Home > Mobile >  Repeating each element in a list by a specified number
Repeating each element in a list by a specified number

Time:04-19

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)
  • Related