Reputation: 1057
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
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
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
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
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