How to make the length of a nested list equal to the value of a number in a list, using list comprehension?

Question:

I’m really new to Python, so forgive me if this is a ridiculously simple question.
I have a given list

x = [0,1,2,3,4,5,6,7,8,9]

Now I want to make a list e, using list comprehension, that contains a list for each odd element of list x. All inner elements of this list should be true and the number of list elements is given by the current number of x. So it should look like this:

[[], [True, True], [True, True, True, True], ...]

The code I have so far is:

e = [[True for z in x] for z in x if z % 2 != 0]

When printed I get a list, where the amount of nested lists is equal to the amount of odd numbers in list x, but all of them contain True ten times. What do I have to do to make the lengths of the inner lists equal to the values of the odd numbers?

Asked By: laryberry

||

Answers:

First, the if-condition should be z % 2 == 0, then to create a list of True values you can use [True] * z:

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

e = [[True] * z for z in x if z % 2 == 0]
print(e)

Prints:

[[], [True, True], [True, True, True, True], [True, True, True, True, True, True], [True, True, True, True, True, True, True, True]]

If you don’t want to use [True] * z you can do:

e = [[True for _ in range(z)] for z in x if z % 2 == 0]
Answered By: Andrej Kesely

This code should do what you want:

[[True for _ in range(z)] for z in x if z % 2 != 0]

The difference is in the inner comprehension, [True for _ in range(z)].

Previously, you were iterating over each z in x – so, for each iteration, z is an integer out of x. Then, for each unique z, you were iterating over the entire x again. Since x has 10 elements, that gives you 10 iterations.

Instead, what you want to do is produce an array of [True] with length z. range(z) gives you a guaranteed iterable of length z for which you can generate as many Trues as you need.

The innermost variable name, I replaced with a _, because it isn’t used.

Answered By: Green Cloak Guy

You can use range with step==2.

res = [[True]*e for e in range(0,9,2)]
# Or
res = [[True for _ in range(e)] for e in range(0,9,2)]
print(res)

Output:

[[], [True, True], [True, True, True, True], [True, True, True, True, True, True], [True, True, True, True, True, True, True, True]]

Explanation:

>>> list(range(0,9,2))
[0, 2, 4, 6, 8]
Answered By: I'mahdi

Searching for odd numbers could be done like this:

def generate_number_list(quantity: int):
    """
    This creates a list of numbers
    """
    number_list = []
    for number in range(quantity):
        number_list.append(number) 
        
    return number_list


def main():
    number_list = generate_number_list(10)
    odd_number_sub_lists = []
    
    # Be careful with list comprehensions. Storing them
    # could cause unexpected behaviour
    [
        odd_number_sub_lists.append(
            
            # Nested list comprehension that uses the current_number
            # as a range, only when its an odd number.
            [True for count in range(current_number)]
        )
        for current_number in number_list
        
        # As you typed odd Numbers. All of the previous
        # statements only work if the current_number
        # divided by two gives a residue greater than 0
        if (current_number % 2 > 0)  
    ]
    return odd_number_sub_lists
    
    
if __name__ == '__main__':
    result = main()
    print(result)

Result:

[[True], [True, True, True], [True, True, True, True, True], [True, True, True, True, True, True, True], [True, True, True, True, True, True, True, True, True]]

Now, for the output you wanted, it would be for even numbers. The only thing you would need to change is this statement:

if (current_number % 2 > 0)  

For this:

if (current_number % 2 == 0)  
Answered By: Kyostenas