给出一个清单
a = [0,1,2,3,4,5,6,7,8,9]
我怎样才能获得
b = [0,9,1,8,2,7,3,6,4,5]
也就是说,产生一个新的列表,其中每个连续的元素交替地从原始列表的两边取出?
答案 0 :(得分:26)
cycle
和iter
获取商品之间的 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]