Duplicating list items variable number of times with list comprehension

Question:

I am basically trying to get my head around using a list comprehension with this basic bit of code. Im trying to duplicate a list item by the value of the list item:

y = [1, 2, 0, 1]
x = []
for i in y:
    for j in range(i):
        x.append(i)
# Desired output
>>> [1, 2, 2, 1]

x = [i for _ in range(i) for i in y]
# Wrong output
>>> [1, 2, 0, 1]

# Right output
x = [j for j in y for _ in range(j)]
>>> [1, 2, 2, 1]

I just cant seem to get my head around why I get the wrong output for the second example. Could someone explain what is wrong here. Thanks.

Asked By: kezzos

||

Answers:

The right comprehension is:

x = [i for i in y for j in range(i)]

This give the result you want
item for item in list range(item) times
inspired by this thread

flattened = [val for sublist in list_of_lists for val in sublist]
Answered By: mquantin
x = [j for j in y for i in range(j)]
Answered By: khelili miliana

When you have multiple for loops inside a list comprehension, the loops are processed in the same order as they would be using “traditional” for loops. Your list comp that gives the correct output has the loops in the same order as your code at the start using .append with traditional for loops.

As Rahul mentions in the comments, in isolation,

x = [i for _ in range(i) for i in y]

would give a

NameError: name 'i' is not defined

It doesn’t in this case because i was defined by the earlier code.


In contrast, look at what happens with a nested list comp:

y = [1, 2, 0, 1]
x = [[j for j in range(i)] for i in y]
print(x)    

output

[[0], [0, 1], [], [0]]

Here, the outermost loop is in the outer comprehension and the inner loop is in the inner comprehension. So for each iteration of the for i in y we create a new list comp, and in that list comp we loop over range(i).

Answered By: PM 2Ring
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.