如果我有一个列表test
test = [i for i in range(20)]
print(test)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
我希望每5个数字得到最后3个数字,这样我得到的列表如下:
[2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19]
有没有办法用列表切片来做到这一点?我可以使用像
这样的模数函数来完成它[i for i in test if i % 5 > 1]
但是我想知道是否有办法用列表切片来做到这一点?感谢
答案 0 :(得分:3)
使用filter功能:
list(filter(lambda x: x % 5 > 1, test)) # [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19]
答案 1 :(得分:1)
如果订购无关紧要,您可以尝试以下方法:
test[2::5] + test[3::5] + test[4::5]
或者更一般地说
start = 2 #Number of indices to skip
n = 5
new_test = []
while start < 5:
b.extend(test[start::n])
start += 1
答案 2 :(得分:0)
是的,但我非常怀疑它会比简单的列表理解更快:
from itertools import chain, zip_longest as zipl
def offset_modulo(l, x, n):
sentinel = object()
slices = (l[i::n] for i in range(x, n))
iterable = chain.from_iterable(zipl(*slices, fillvalue=sentinel))
return list(filter(lambda x: x is not sentinel, iterable))
print(offset_modulo(range(20), 2, 5))
# [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19]
print(offset_modulo(range(24), 2, 5))
# [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19, 22, 23]
基本上,此方法获取表示每个索引i
的列表切片,使i % n >= x
。然后,它会使用zip
和chain
将这些内容展平为输出。
编辑:
更简单的方法
def offset(l, x, n):
diff = n-x
slices = (l[i:i+diff] for i in range(x, len(l), n))
return list(chain.from_iterable(slices))
offset(range(20), 2, 5)
# [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19]
offset(range(24), 2, 5)
# [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19, 22, 23]
在我们得到我们想要的相邻元素的切片的地方,然后chain
那些在一起。
答案 3 :(得分:0)
我建议这个解决方案:
from functools import reduce
reduce(lambda x, y: x + y, zip(test[2::5], test[3::5], test[4::5]))
使用timeit
进行测试,它比过滤器和理解列表更快(至少在我的电脑上)。
这里是执行执行时间比较的代码:
import numpy as np
import timeit
a = timeit.repeat('list(filter(lambda x: x % 5 > 1, test))',
setup='from functools import reduce; test = list(range(20))',
repeat=20,
number=100000)
b = timeit.repeat('[i for i in test if i % 5 > 1]',
repeat=20,
setup='test = list(range(20))',
number=100000)
c = timeit.repeat('reduce(lambda x, y: x + y, zip(test[2::5], test[3::5], test[4::5]))',
repeat=20,
setup='from functools import reduce;test = list(range(20))',
number=100000)
list(map(lambda x: print("{}:\t\t {} ({})".format(x[0], np.mean(x[1]), np.std(x[1]))),
[("filter list", a),
('comprehension', b),
('reduce + zip', c)]))
之前的代码产生以下结果:
filter list: 0.2983790061000036 (0.007463432805174629)
comprehension: 0.15115660065002884 (0.004455055805853705)
reduce + zip: 0.11976779574997636 (0.002553487341208172)
我希望这有助于:)