从交替的边循环列表

时间:2016-04-10 18:11:14

标签: python algorithm list iteration

给出一个清单

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

我怎样才能获得

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

也就是说,产生一个新的列表,其中每个连续的元素交替地从原始列表的两边取出?

12 个答案:

答案 0 :(得分:26)

从正向cycleiter获取商品之间的

reversed。只需确保您使用islice停在len(a)

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]

这可以很容易地放在一行,但后来变得更难阅读:

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

将它放在一行中也会阻止你使用另一半迭代器,如果你想:

>>> 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]

答案 1 :(得分:8)

Python 2.7中的一个非常好的单行程序:

#include<stdio.h>
void main()
{
int i=10;
printf("%d %d %d\n",a,--a,++a); // output  10 10 10

}

首先用反向压缩列表,取 half 该列表,将元组加起来形成一个元组,然后转换为列表。

在Python 3中,results = list(sum(zip(a, reversed(a))[:len(a)/2], ())) >>>> [0, 9, 1, 8, 2, 7, 3, 6, 4, 5] 会返回一个生成器,因此您必须使用zip中的islice

itertools

编辑:看起来这只适用于偶数列表长度 - 奇数列表长度将省略中间元素:( from itertools import islice results = list(sum(islice(zip(a, reversed(a)),0,int(len(a)/2)),())) int(len(a)/2)的小修正会给你一个重复的中间值,所以请注意。

答案 2 :(得分:6)

你可以来回pop

b = [a.pop(-1 if i%2 else 0) for i in range(len(a))]

注意:这会破坏原始列表a

答案 3 :(得分:6)

使用右toolz

from toolz import interleave, take

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

首先,我尝试使用itertools(Python 3)尝试类似Raymond Hettinger的解决方案。

from itertools import chain, islice

interleaved = chain.from_iterable(zip(a, reversed(a)))
b = list(islice(interleaved, len(a)))

答案 4 :(得分:5)

与其他一些答案没有太大的不同,但它避免了用于确定索引符号的条件表达式。

a = range(10)
b = [a[i // (2*(-1)**(i&1))] for i in a]

i & 1在0和1之间交替。这使得指数在1和-1之间交替。 导致索引除数在2和-2之间交替,这导致索引在i增加时从头到尾交替。序列为a[0]a[-1]a[1]a[-2]a[2]a[-3]等。

(我在i上重复a,因为在这种情况下,a的每个值都等于其索引。通常,迭代range(len(a))。)

答案 5 :(得分:4)

{{1}}

注意:

  

谨防:就像@Tadhg McDonald-Jensen所说(见下面的评论)   它会破坏原始列表对象的一半。

答案 6 :(得分:4)

不确定,这是否可以更紧凑地编写,但它是有效的,因为它只使用迭代器/生成器

var arr = [{    
    "series": [{    
        "name": 2014,    
        "data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18]    
    }, {    
        "name": 2015,    
        "data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30]    
    }]    
}, {    
    "series": [{    
        "name": 2014,    
        "data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18]    
    }, {    
        "name": 2015,    
        "data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30]    
    }]    
}];    


_.chain(arr)    
    .map('series')    
    .flatten()    
    .reduce(function(object, value) {    
        object[value.name] = !object[value.name] ? value.data : _.union(object[value.data], value.data);    
        return object;    
    }, {})    
    .reduce(function(arr, value, key) {    
        arr.push({    
            year: key,    
            data: value    
        });    
        return arr;    
    }, [])    
    .value();    

答案 7 :(得分:4)

一点也不优雅,但它是一个笨拙的单行:

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

请注意,它假设您为偶数长度列表执行此操作。如果中断,则会中断(它会中断)。请注意,我从here获得了一些想法。

答案 8 :(得分:4)

为了好玩,这里有一个itertools变体:

>>> a = [0,1,2,3,4,5,6,7,8,9]
>>> list(chain.from_iterable(izip(islice(a, len(a)//2), reversed(a))))
[0, 9, 1, 8, 2, 7, 3, 6, 4, 5]

这适用于len(a)均匀的情况。它需要一个奇数加长输入的特殊代码。

享受!

答案 9 :(得分:4)

尚未见到的两个版本:

b = list(sum(zip(a, a[::-1]), ())[:len(a)])

import itertools as it

b = [a[j] for j in it.accumulate(i*(-1)**i for i in range(len(a)))]

答案 10 :(得分:3)

我会做这样的事情

a = [0,1,2,3,4,5,6,7,8,9]
b = []
i = 0
j = len(a) - 1
mid = (i + j) / 2
while i <= j:
    if i == mid and len(a) % 2 == 1:
        b.append(a[i])
        break
    b.extend([a[i], a[j]])
    i = i + 1
    j = j - 1

print b

答案 11 :(得分:2)

您可以将列表分为中间两部分,反转后半部分并压缩两个分区,如下所示:

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)

输出:

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