簡體   English   中英

每 n 個位置將列表中的項目插入到另一個列表

[英]Insert items from list to another list every n positions

我有以下清單。

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

我想通過插入每兩個元素來獲得以下內容。

output = [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

不僅 Python 列表而且使用 numpy 數組的答案也很好。

我不認為有一種簡單的 NumPy 方法可以對任何可能大小的數組執行此操作,但這里有一種使用迭代器和列表理解來執行此操作的 Python 方法:

it1, it2 = map(iter, (vector, inserted_elements))
n = sum(map(len, (vector, inserted_elements)))

[next(it2) if i % 3 == 0 else next(it1) for i in range(1, n+1)]
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

在輸出的每個第三元素將來自it2 ,對於迭代器inserted_elements 其余的來自it1對應於vector

numpy 數組步驟:

1.

>>> a=np.reshape(np.matrix([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),(5, 2))
>>> a
matrix([[ 1,  2],
        [ 3,  4],
        [ 5,  6],
        [ 7,  8],
        [ 9, 10]])

2.

>>> b=np.reshape(np.matrix([2, 2, 2, 2, 2]),(5, 1))
>>> b
matrix([[2],
        [2],
        [2],
        [2],
        [2]])

3.

>>> M = np.append(a, b, axis=1)
>>> M
matrix([[ 1,  2,  2],
        [ 3,  4,  2],
        [ 5,  6,  2],
        [ 7,  8,  2],
        [ 9, 10,  2]])

4.

>>> result=np.array(M).flatten()
>>> result
array([ 1,  2,  2,  3,  4,  2,  5,  6,  2,  7,  8,  2,  9, 10,  2])

傳統的for循環的做法可能會像下面這樣,當你隨意從2元vector ,並從1元inserted_elements ,使output列表

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

output = []

#Pick two elements from vector and one element from inserted_elements and add it to output list
for idx in range(0,len(vector),2):

    output.extend(vector[idx:idx+2] + [inserted_elements[int(idx/2)]])

print(output)

列表理解中的相同內容將是

output = [ v for idx in range(0,len(vector),2) for v in vector[idx:idx+2] + [inserted_elements[int(idx/2)]]]

輸出將是

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

這是一種有點晦澀的方法 - 但它比其他任何方法都快(到目前為止):

list(itertools.chain(*zip(*[iter(vector)]*2+[iter(inserted_elements)]))) 

它使用“慣用語”來獲取大小為 n 組的項目, [iter(alist)]*nitertools.chain作為展平嵌套列表的一種方式。

已刪除的答案使用np.insert 為此,我相信insert使用掩碼,如下所示:

def foo(vector, inserted_elements):
    res = np.zeros(len(vector)+len(inserted_elements),int)  
    mask = res.astype(bool) 
    mask[2::3]=True 
    res[mask]=inserted_elements 
    res[~mask]=vector    
    return res

np.append答案的一個變體是:

np.column_stack((np.reshape(vector,(-1,2)), inserted_elements)).ravel()

我通常不喜歡np.append ,因為它經常被濫用,尤其是在循環中。 為此,沒關系,但我認為column_stack更干凈。

===

In [254]: list(zip(*[iter(vector)]*2+[iter(inserted_elements)]))                                         
Out[254]: [(1, 2, 2), (3, 4, 2), (5, 6, 2), (7, 8, 2), (9, 10, 2)]

這是一種基於itertools的方法,它也適用於從一個列表插入到另一個列表的任意數量的元素。 為此,我定義了一個生成器函數,它將把l2元素插入到l1i項目:

def insert_every_n(l1, l2, k):
    i1, i2 = iter(l1), iter(l2)
    while True:
        try:
            yield from islice(i1, k)
            yield next(i2)
        except StopIteration:
            return

這是通過使用itertools.islice在每次迭代中從迭代器l1產生最多i項目來實現的。 使用yield from我們產生的項目與切片可迭代中的項目一樣多,因此可迭代運行到耗盡,( for v in g: yield v的快捷方式for v in g: yield v )。

最后,我們可以用try / expect來包裝yield語句以捕獲StopIteration警告。


讓我們嘗試使用建議的示例:

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2, 2]

list(insert_every_n(vector, inserted_elements, k=2))
# [1, 2, 2, 3, 4, 2, 5, 6, 2, 7, 8, 2, 9, 10, 2]

如果我們想每 3 個項目添加一個l2項目:

vector = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
inserted_elements = [2, 2, 2, 2]

list(insert_every_n(vector, inserted_elements, k=3))
# [1, 2, 3, 2, 4, 5, 6, 2, 7, 8, 9, 2, 10, 2]

暫無
暫無

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

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