sunspots
sunspots

Reputation: 1057

One-liner for nearly redundant list comprehensions

Consider two list comprehensions gamma and delta with nearly redundant code. The difference being the sliced lists alpha and beta, namely

gamma = [alpha[i:i+30] for i in range(0,49980,30)]
delta = [beta[i:i+30] for i in range(0,49980,30)]

Is there a pythonic way to write this as a one liner (say gamma,delta = ... )?

I have a few other pieces of code that are similar in nature, and I'd like to simplify the code's seeming redundancy.

Upvotes: 4

Views: 161

Answers (4)

Stefan Pochmann
Stefan Pochmann

Reputation: 28596

Just another way...

gamma, delta = ([src[i:i+30] for i in range(0,49980,30)] for src in (alpha, beta))

It's a bit faster than the accepted zip solution:

genny 3.439506340350704
zippy 4.3039169818228515

Code:

from timeit import timeit
alpha = list(range(60000))
beta = list(range(60000))
def genny():
    gamma, delta = ([src[i:i+30] for i in range(0,49980,30)] for src in (alpha, beta))
def zippy():
    gamma, delta = zip(*[(alpha[i:i+30], beta[i:i+30]) for i in range(0,50000,30)])
n = 1000
print('genny', timeit(genny, number=n))
print('zippy', timeit(zippy, number=n))

Upvotes: 1

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48067

As far as your question related to combining both the list comprehension expression above is concerned, you can get gamma and delta by using zip with single list comprehension as:

gamma, delta = zip(*[(alpha[i:i+30], beta[i:i+30]) for i in range(0,50000,30)])

Sample example to show how zip works:

>>> zip(*[(i, i+1) for i in range(0, 10, 2)])
[(0, 2, 4, 6, 8), (1, 3, 5, 7, 9)]

Here our list comprehension will return the list of tuples:

>>> [(i, i+1) for i in range(0, 10, 2)]
[(0, 1), (2, 3), (4, 5), (6, 7), (8, 9)]

Then we are unpacking this list using * and using zip we are aggregating the element from each of the iterables:

>>> zip(*[(i, i+1) for i in range(0, 10, 2)])
[(0, 2, 4, 6, 8), (1, 3, 5, 7, 9)]

As an alternative, for dividing the list into evenly sized chunks, please take a look at "How do you split a list into evenly sized chunks?"

Upvotes: 4

Joe Iddon
Joe Iddon

Reputation: 20414

Although one-line list-comprehensions are really useful, they aren't always the best choice. So here since you're doing the same chunking to both lists, if you wanted to change the chunking, you would have to modify both lines.

Instead, we could use a function that would chunk any given list and then use a one-line assignment to chunk gamma and delta.

def chunk(l):
    return [l[i:i+30] for i in range(0, len(l), 30)]

gamma, delta = chunk(gamma), chunk(delta)

Upvotes: 8

Noa
Noa

Reputation: 145

You can you lambda expression:

g = lambda l: [l[i:i+30] for i in range(0,50000, 30)]
gamma, delta = g(alpha), g(beta)

Upvotes: 0

Related Questions