簡體   English   中英

在 Python 列表中每第 n 個元素后插入元素

[英]Insert element in Python list after every nth element

假設我有一個 Python 列表,如下所示:

letters = ['a','b','c','d','e','f','g','h','i','j']

我想在每個第 n 個元素后插入一個“x”,比方說該列表中的三個字符。 結果應該是:

letters = ['a','b','c','x','d','e','f','x','g','h','i','x','j']

我知道我可以通過循環和插入來做到這一點。 我實際上正在尋找的是一種 Pythonish 方式,也許是一種單行代碼?

我有兩個合一的襯墊。

鑒於:

>>> letters = ['a','b','c','d','e','f','g','h','i','j']
  1. 使用enumerate讓指數,加上'x' ,每3信件,mod(n, 3) == 2 ,然后連接成字符串list()它。

     >>> list(''.join(l + 'x' * (n % 3 == 2) for n, l in enumerate(letters))) ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']

    但正如@sancho.s 指出的那樣,如果任何元素有多個字母這將不起作用。

  2. 使用嵌套理解來展平列表(a)的列表,以 3 為'x'組切片,如果距離列表末尾少於 3,則添加'x'

     >>> [x for y in (letters[i:i+3] + ['x'] * (i < len(letters) - 2) for i in xrange(0, len(letters), 3)) for x in y] ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']

(a) [item for subgroup in groups for item in subgroup]使列表的鋸齒狀列表變平。

嘗試這個

i = n
while i < len(letters):
    letters.insert(i, 'x')
    i += (n+1)

其中n是在您想要插入'x'元素數量之后。

這通過初始化變量i並將其設置為等於n 然后設置一個while循環,該循環在i小於letters長度時運行。 然后在letters i的索引處插入'x' 然后您必須將n+1的值添加到i 您必須執行n+1而不僅僅是n的原因是因為當您將一個元素插入到letters ,它會將列表的長度擴大一。

用你的例子試試這個,其中n是 3 並且你想插入'x' ,它看起來像這樣

letters = ['a','b','c','d','e','f','g','h','i','j']
i = 3
while i < len(letters):
    letters.insert(i, 'x')
    i += 4

print letters

哪個會打印出來

['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']

這是您的預期結果。

我想為每個項目添加一個新元素。

這個怎么樣 ?

a=[2,4,6]
for b in range (0,len(a)):
    a.insert(b*2,1)

現在是

[1, 2, 1, 4, 1, 6]

盡管在for循環中使用list.insert()似乎內存效率更高,但為了在一行中執行此操作,您還可以將給定的值附加到在每個nth索引上拆分的每個等分塊的末尾列表。

>>> from itertools import chain

>>> n = 2
>>> ele = 'x'
>>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

>>> list(chain(*[lst[i:i+n] + [ele] if len(lst[i:i+n]) == n else lst[i:i+n] for i in xrange(0, len(lst), n)]))
[0, 1, 'x', 2, 3, 'x', 4, 5, 'x', 6, 7, 'x', 8, 9, 'x', 10]

這是一個古老的話題,但它缺少最簡單、最“pythonic”的解決方案 imo。 它只不過是Mark Mikofski 已接受答案的第 2 部分的擴展,可以說提高了可讀性(因此使其更加 Python 化)。

>>> letters = ['a','b','c','d','e','f','g','h','i','j']
>>> [el for y in [[el, 'x'] if idx % 3 == 2 else el for 
     idx, el in enumerate(letters)] for el in y]

['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']

一個非常簡單的方法:

>>> letters = ['a','b','c','d','e','f','g','h','i','j']
>>> new_list = []
>>> n = 3
>>> for start_index in range(0, len(letters), n):
...     new_list.extend(letters[start_index:start_index+n])
...     new_list.append('x')
... 
>>> new_list.pop()
'x'
>>> new_list
['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']

您還可以使用grouper食譜從分塊迭代工具文檔。

也值得說明簡單的實現:

letters = ['a','b','c','d','e','f','g','h','i','j']

i = 3   #initial step
while i < len(letters):
    letters.insert(i,'x')
    i = i + 3 + 1  #increment step by one for every loop to account for the added element

它確實使用了基本的循環和插入,但與單行示例相比,它看起來也更簡單、更易於閱讀,恕我直言,它首先按照要求使其更像Python 風格

for 循環已經可以選擇以某個值遞增/遞減:

letters = ['a','b','c','d','e','f','g','h','i','j']
n = 3

for i in range ( n, len(letters)+n, n+1 ):
  letters.insert ( i, 'X' )

print ( letters )

它不需要除法或模運算,只需加法和一種尺寸計算。 輸出:

['a', 'b', 'c', 'X', 'd', 'e', 'f', 'X', 'g', 'h', 'i', 'X', 'j']

雖然Mark Mikofski答案有效,但通過分配切片有一個更快的解決方案:

import string

# The longer the list the more speed up for list3
# letters = ['a','b','c','d','e','f','g','h','i','j']
letters = list(string.ascii_letters)
print("org:", letters)

# Use enumerate to get index, add 'x' every 3rd letter, eg: mod(n, 3) == 2, then concatenate into string and list() it.
list1 = list(''.join(l + 'x' * (n % 3 == 2) for n, l in enumerate(letters)))
print("list1:", list1)
%timeit list(''.join(l + 'x' * (n % 3 == 2) for n, l in enumerate(letters)))

# But as @sancho.s points out this doesn't work if any of the elements have more than one letter.
# Use nested comprehensions to flatten a list of lists(a), sliced in groups of 3 with 'x' added if less than 3 from end of list.
list2 = [x for y in (letters[i:i+3] + ['x'] * (i < len(letters) - 2) for i in range(0, len(letters), 3)) for x in y]
print("list2:", list2)
%timeit [x for y in (letters[i:i+3] + ['x'] * (i < len(letters) - 2) for i in range(0, len(letters), 3)) for x in y]

# Use list slice assignments
len_letters = len(letters)
len_plus_x = ll // 3
list3 = [None for _ in range(len_letters + len_plus_x)]
list3[::4] = letters[::3]
list3[2::4] = letters[2::3]
list3[1::4] = letters[1::3]
list3[3::4] = ['x' for _ in range(len_plus_x)]
print("list3:", list3)
%timeit ll = len(letters); lp = ll//3; new_letters = [None for _ in range(ll + lp)]; new_letters[::4] = letters[::3]; new_letters[2::4] = letters[2::3]; new_letters[1::4] = letters[1::3]; new_letters[3::4] = ['x' for _ in range(lp)]

產生(使用 jupyter notebook)

org: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
list1: ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j', 'k', 'l', 'x', 'm', 'n', 'o', 'x', 'p', 'q', 'r', 'x', 's', 't', 'u', 'x', 'v', 'w', 'x', 'x', 'y', 'z', 'A', 'x', 'B', 'C', 'D', 'x', 'E', 'F', 'G', 'x', 'H', 'I', 'J', 'x', 'K', 'L', 'M', 'x', 'N', 'O', 'P', 'x', 'Q', 'R', 'S', 'x', 'T', 'U', 'V', 'x', 'W', 'X', 'Y', 'x', 'Z']
13 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
list2: ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j', 'k', 'l', 'x', 'm', 'n', 'o', 'x', 'p', 'q', 'r', 'x', 's', 't', 'u', 'x', 'v', 'w', 'x', 'x', 'y', 'z', 'A', 'x', 'B', 'C', 'D', 'x', 'E', 'F', 'G', 'x', 'H', 'I', 'J', 'x', 'K', 'L', 'M', 'x', 'N', 'O', 'P', 'x', 'Q', 'R', 'S', 'x', 'T', 'U', 'V', 'x', 'W', 'X', 'Y', 'x', 'Z']
13.7 µs ± 336 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
list3: ['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j', 'k', 'l', 'x', 'm', 'n', 'o', 'x', 'p', 'q', 'r', 'x', 's', 't', 'u', 'x', 'v', 'w', 'x', 'x', 'y', 'z', 'A', 'x', 'B', 'C', 'D', 'x', 'E', 'F', 'G', 'x', 'H', 'I', 'J', 'x', 'K', 'L', 'M', 'x', 'N', 'O', 'P', 'x', 'Q', 'R', 'S', 'x', 'T', 'U', 'V', 'x', 'W', 'X', 'Y', 'x', 'Z']
4.86 µs ± 35.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

我會將問題分解為兩個問題。 首先將列表分成塊,然后將它們與您要插入的任何其他內容連接起來。

from itertools import chain

def join_at(elements: list, item: object, n: int) -> list:
    # lambda for inserting the element when chunking
    insert = lambda i: [] if i == 0 else [item]
    # chunk up the original list based on where n lands, inserting the element along the way
    chunked = [insert(i) + elements[i:i+n] for i in range(0, len(elements), n)]
    # flatten the chunks back out
    return list(chain(*chunked))

print(join_at([0,1,2,3,4,5,6,7,8,9], 'x', 3))

這將在 output 的原始列表中每隔 3 個 position 插入一個x

[0, 1, 2, 'x', 3, 4, 5, 'x', 6, 7, 8, 'x', 9]

l = ['a','b','c','d','e','f','g','h','i','j']
[ l.insert(n+(n+1)*i, 'x') for i in range(len(l)/n) ]
print l

暫無
暫無

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

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