簡體   English   中英

每n個n-2分割一次Python列表切片

[英]Python list slicing for n-2 every n

如果我有清單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]

但是我想知道是否有一種方法可以使用列表切片? 謝謝

使用過濾器功能:

list(filter(lambda x: x % 5 > 1, test))  # [2, 3, 4, 7, 8, 9, 12, 13, 14, 17, 18, 19]

如果訂購無關緊要,則可以嘗試以下操作:

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

是的,但是我非常懷疑這將比簡單的列表理解要快:

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 然后,它使用zipchain將其平展到輸出中。

編輯:

更簡單的方法

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在一起。

我提出以下解決方案:

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)

我希望這可以幫助:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM