Вставить элемент в список Python после каждого n-го элемента

Скажем, у меня есть список Python:

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

Я хочу вставить "x" после каждого n-го элемента, пусть скажут три символа в этом списке. Результат должен быть:

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

Я понимаю, что могу сделать это с помощью цикла и вставки. То, что я на самом деле ищу, - это Pythonish-way, может быть, однострочный?

Ответы

Ответ 1

У меня два лайнера.

Дано:

>>> 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 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] выравнивает зубчатый список списков.

Ответ 2

Попробуйте это

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

где n - после того, сколько элементов вы хотите вставить 'x'.

Это работает, инициализируя переменную i и устанавливая ее равной n. Затем вы настраиваете цикл while, который выполняется, пока i меньше длины letters. Затем вы вставляете 'x' в индекс i в letters. Затем вы должны добавить значение 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']

который является вашим ожидаемым результатом.

Ответ 3

Хотя использование list.insert() в цикле for кажется более эффективным с точки зрения памяти, для того, чтобы сделать это в одной строке, вы также можете добавить данное значение в конце каждого поделенного разделения фрагментов на каждом 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]

Ответ 4

Довольно простой метод:

>>> 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 из документации itertools для фрагментации.

Ответ 5

Я хочу добавить новый элемент для каждого элемента.

Как насчет этого?

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

a теперь

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

Ответ 6

Это старая тема, но в ней отсутствует самое простое, "питоническое" решение, imo. Это не более чем продолжение второй части принятого ответа Марка Микофски, которое, возможно, улучшает читабельность (и, следовательно, делает его более питоническим).

>>> 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']

Ответ 7

В то время как ответ Марка Микофски работает, есть более быстрое решение, назначая слайсы:

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)

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)

Ответ 8

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