我想知道Python中是否有标准库函数可以像以下示例那样重新排列列表元素:
a = [1,2,3,4,5,6,7]
function(a)
print a
a = [1,7,2,6,3,5,4]
该算法应该从原始列表的开头获取一个元素,然后从末尾取一个元素,接着再从开头取第二个元素,以此类推。然后重新排列该列表。
敬礼,
a = [1,2,3,4,5,6,7]
function(a)
print a
a = [1,7,2,6,3,5,4]
该算法应该从原始列表的开头获取一个元素,然后从末尾取一个元素,接着再从开头取第二个元素,以此类推。然后重新排列该列表。
敬礼,
itertools
构建一个快速、内存高效的生成器,该生成器可以满足你的需求:from itertools import chain, izip
def reorder(a):
gen = chain.from_iterable(izip(a, reversed(a)))
for _ in a:
yield next(gen)
>>> list(reorder(a))
<<< [1, 7, 2, 6, 3, 5, 4]
itertools
有很多构建迭代器的强大工具。一个更加简洁的解决方案是:>>> list(chain.from_iterable(izip(a, reversed(a))))[:len(a)]
<<< [1, 7, 2, 6, 3, 5, 4]
列表推导式是构建列表的另一种非常简洁的方式:
>>> [x for t in zip(a, reversed(a)) for x in t][:len(a)]
<<< [1, 7, 2, 6, 3, 5, 4]
最后,这里有一个有趣的短语:
>>> sum(zip(a, a[::-1]), ())[:len(a)]
<<< (1, 7, 2, 6, 3, 5, 4)
gen = chain(*izip(a, reversed(a)))
呢? - johnsyweb*izip
不是记忆效率高的,因为它必须立即扩展所有迭代器。您需要 chain.from_iterable(izip(a, reversed(a)))
。 - agfx = len(list) - 1
y = len(list)/2
for i in xrange(y):
if list[i] not in new_list:
new_list.append(list[i])
if list[i+x] not in new_list:
new_list.append(list[i+x])
x -= 2
if len(list)%2 == 1:
new_list.append(list[y])
#print "new list is: ", new_list
return new_list
- alwbtc>>> ((a+a[:0:-1])*len(a))[::len(a)][:len(a)]
[1, 7, 2, 6, 3, 5, 4]
for a in ([1,2,3,4,5,6,7,8,9],
[1,2,3,4,5,6,7,8],
[1,2,3,4],
[1,2,3],
[1,2,],
[1],
[]):
print a
[ a.insert(i,a.pop()) for i in xrange(1,len(a)+1,2)]
print a,'\n'
结果
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 9, 2, 8, 3, 7, 4, 6, 5]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 8, 2, 7, 3, 6, 4, 5]
[1, 2, 3, 4]
[1, 4, 2, 3]
[1, 2, 3]
[1, 3, 2]
[1, 2]
[1, 2]
[1]
[1]
[]
[]
与 zeekay 的代码相比:
from time import clock
n = 100000
te = clock()
for i in xrange(n):
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
[ a.insert(i,a.pop()) for i in xrange(1,len(a)+1,2)]
print clock()-te
from itertools import chain, izip
def reorder(a):
gen = chain(*izip(a, reversed(a)))
for _ in a:
yield next(gen)
te = clock()
for i in xrange(n):
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
a = list(reorder(a))
print clock()-te
结果
2.36667984339
5.00051766356
我的方法会直接在原地更改a
def function(a):
ret = []
this_end, other_end = 0, -1
while a:
ret.append(a.pop(this_end))
this_end, other_end = other_end, this_end
return ret
a = [1,2,3,4,5,6,7]
print function(a)
关于时间:
% python -m timeit 'def function(a):
quote> ret = []
quote> this_end, other_end = 0, -1
quote> while a:
quote> ret.append(a.pop(this_end))
quote> this_end, other_end = other_end, this_end
quote> return ret
quote>
quote> a = [1,2,3,4,5,6,7]
quote>
quote> print function(a)
quote> ' | tail
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
[1, 7, 2, 6, 3, 5, 4]
100000 loops, best of 3: 10.5 usec per loop
谢谢大家,我已经编写了自己的函数:
def shake(list):
"""Gets a list and reorders the items,
one from beginning, one from end"""
#print "original list is: ", list
new_list = []
x = len(list) - 1
y = len(list)/2
for i in xrange(y):
if list[i] not in new_list:
new_list.append(list[i])
if list[i+x] not in new_list:
new_list.append(list[i+x])
x -= 2
if len(list)%2 == 1:
new_list.append(list[y])
#print "new list is: ", new_list
return new_list