I feel like I spend a lot of time writing code in Python, but not enough time creating Pythonic code. Recently I ran into a funny little problem that I thought might have an easy, idiomatic solution. Paraphrasing the original, I needed to collect every sequential pair in a list. For example, given the list [1,2,3,4,5,6]
, I wanted to compute [(1,2),(3,4),(5,6)]
.
I came up with a quick solution at the time that looked like translated Java. Revisiting the question, the best I could do was
l = [1,2,3,4,5,6] [(l[2*x],l[2*x+1]) for x in range(len(l)/2)]
which has the side effect of tossing out the last number in the case that the length isn't even.
Is there a more idiomatic approach that I'm missing, or is this the best I'm going to get?
To get every other element in a Python list you can use the slice operator and use the fact that this operator allows to provide a step argument (with its extended syntax). Another approach is to use the mathematical concept of remainder and apply it to list indexes.
To iterate over all pairs of consecutive items in a list with Python, we can use zip with a for loop.
Using for Loops You can use a for loop to create a list of elements in three steps: Instantiate an empty list. Loop over an iterable or range of elements. Append each element to the end of the list.
This will do it a bit more neatly:
>>> data = [1,2,3,4,5,6] >>> zip(data[0::2], data[1::2]) [(1, 2), (3, 4), (5, 6)]
(but it's arguably less readable if you're not familiar with the "stride" feature of ranges).
Like your code, it discards the last value where you have an odd number of values.
The one often-quoted is:
zip(*[iter(l)] * 2)
I prefer this more readable version of the iter
solution:
it = iter(l) list(zip(it, it)) # [(1, 2), (3, 4), (5, 6)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With