Pythonic - 2 years ago 95
Python Question

# Cycle a list from alternating sides

Given a list

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

how can I get

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

That is, produce a new list in which each successive element is alternately taken from the two sides of the original list?

``````>>> [a[-i//2] if i % 2 else a[i//2] for i in range(len(a))]
[0, 9, 1, 8, 2, 7, 3, 6, 4, 5]
``````

Explanation:
This code picks numbers from the beginning (`a[i//2]`) and from the end (`a[-i//2]`) of `a`, alternatingly (`if i%2 else`). A total of `len(a)` numbers are picked, so this produces no ill effects even if `len(a)` is odd.
`[-i//2 for i in range(len(a))]` yields `0, -1, -1, -2, -2, -3, -3, -4, -4, -5`,
`[ i//2 for i in range(len(a))]` yields `0, 0, 1, 1, 2, 2, 3, 3, 4, 4`,
and `i%2` alternates between `False` and `True`,
so the indices we extract from `a` are: `0, -1, 1, -2, 2, -3, 3, -4, 4, -5`.

My assessment of pythonicness:
The nice thing about this one-liner is that it's short and shows symmetry (`+i//2` and `-i//2`).
The bad thing, though, is that this symmetry is deceptive:
One might think that `-i//2` were the same as `i//2` with the sign flipped. But in Python, integer division returns the floor of the result instead of truncating towards zero. So `-1//2 == -1`.
Also, I find accessing list elements by index less pythonic than iteration.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download