Andrés
Andrés

Reputation: 5

Divide a Python list every n-element

Recently, I've found a code for developing a set of lists from a list, that code was written by user Mai, answering question but i have not understood it yet. Could somebody help me to understand it? And... is there a way to rewrite that code that be easier? The code is:

def even_divide(lst, num_piece=4):
    return [
        [lst[i] for i in range(len(lst)) if (i % num_piece) == r]
        for r in range(num_piece)
    ]

Thanks!

Upvotes: 0

Views: 67

Answers (2)

zerecees
zerecees

Reputation: 699

Could somebody help me to understand it?

Sure! It's a list comprehension. A list comprehension takes a list and does something to or with every element in that list. Let's say I want to multiply every element in my list by 2:

new_list = [element*2 for element in my_list]

What makes it a list comprehension is the bracket syntax. For those new to it, that's usually the part that takes a moment to get used to. With that said, I assume that is what is giving you difficulty in understanding the code in your question, as you have a list comprehension in a list comprehension. It might be difficult to understand now, but list comprehensions are a wonderful thing in python.

But, as this post mentions, there's a lot of discussions around list comprehension, lambda's, map, reduce, and filter. Ultimately, its up to you to decide what's best for your project. I'm not a fan of anything else but list comprehensions, so I use those religiously.

Based on the question you've linked, the list comprehension takes a 1d list of length x and turns it into a 2d list of (length x, width y). It's like numpy.reshape.

And... is there a way to rewrite that code [to] be easier?

I would not recommend it. List comprehensions are considered very pythonic and you will see them everywhere. Best to use them and get used to them.

Upvotes: 0

ShlomiF
ShlomiF

Reputation: 2895

It's pretty simple actually. Just follow through the values of the two loops:

Starting with the outer loop, r would be 0, then 1, then 2, etc. Let's look at the case for which r == 1. When running through the different values of i, (which would be 0, 1, 2, ... len(lst), the value of i % 4, meaning the remainder of dividing i by 4, would be 0, 1, 2, 3, 0, 1, 2, 3, .... So the i % 4 would be equal to r, for every 4 values of i!

For our chosen r == 1, that would mean we're choosing lst[1], lst[5], lst[9], ..., etc.

And for r == 2? You guessed it! You'd be picking up lst[2], lst[6], lst[10],....

So over all you'd get 4 lists, with non-overlapping elements of the original list, by just "jumping" 4 elements every time, but starting at different values.

Which naturally leads to the more simple solution:

def even_divide(lst, num_piece=4):
    return [lst[r::num_piece] for r in range(num_piece)]

Upvotes: 1

Related Questions