Cycle a list from alternating sides

2020-02-08 05:56发布

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?

15条回答
聊天终结者
2楼-- · 2020-02-08 06:06

You can partition the list into two parts about the middle, reverse the second half and zip the two partitions, like so:

a = [0,1,2,3,4,5,6,7,8,9]
mid = len(a)//2
l = []
for x, y in zip(a[:mid], a[:mid-1:-1]):
    l.append(x)
    l.append(y)
# if the length is odd
if len(a) % 2 == 1:
    l.append(a[mid])
print(l)

Output:

[0, 9, 1, 8, 2, 7, 3, 6, 4, 5]
查看更多
劳资没心,怎么记你
3楼-- · 2020-02-08 06:07

Not at all elegant, but it is a clumsy one-liner:

a = range(10)
[val for pair in zip(a[:len(a)//2],a[-1:(len(a)//2-1):-1]) for val in pair]

Note that it assumes you are doing this for a list of even length. If that breaks, then this breaks (it drops the middle term). Note that I got some of the idea from here.

查看更多
混吃等死
4楼-- · 2020-02-08 06:07
mylist = [0,1,2,3,4,5,6,7,8,9]
result = []

for i in mylist:
    result += [i, mylist.pop()]

Note:

Beware: Just like @Tadhg McDonald-Jensen has said (see the comment below) it'll destroy half of original list object.

查看更多
孤傲高冷的网名
5楼-- · 2020-02-08 06:09

Use the right toolz.

from toolz import interleave, take

b = list(take(len(a), interleave((a, reversed(a)))))

First, I tried something similar to Raymond Hettinger's solution with itertools (Python 3).

from itertools import chain, islice

interleaved = chain.from_iterable(zip(a, reversed(a)))
b = list(islice(interleaved, len(a)))
查看更多
叛逆
6楼-- · 2020-02-08 06:15

cycle between getting items from the forward iter and the reversed one. Just make sure you stop at len(a) with islice.

from itertools import islice, cycle

iters = cycle((iter(a), reversed(a)))
b = [next(it) for it in islice(iters, len(a))]

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

This can easily be put into a single line but then it becomes much more difficult to read:

[next(it) for it in islice(cycle((iter(a),reversed(a))),len(a))]

Putting it in one line would also prevent you from using the other half of the iterators if you wanted to:

>>> iters = cycle((iter(a), reversed(a)))
>>> [next(it) for it in islice(iters, len(a))]
[0, 9, 1, 8, 2, 7, 3, 6, 4, 5]
>>> [next(it) for it in islice(iters, len(a))]
[5, 4, 6, 3, 7, 2, 8, 1, 9, 0]
查看更多
疯言疯语
7楼-- · 2020-02-08 06:16

Not sure, whether this can be written more compactly, but it is efficient as it only uses iterators / generators

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

iter1 = iter(a)
iter2 = reversed(a)
b = [item for n, item in enumerate(
        next(iter) for _ in a for iter in (iter1, iter2)
    ) if n < len(a)]
查看更多
登录 后发表回答