Insira um elemento em um índice específico em uma lista e retorne a lista atualizada

99

Eu tenho isto:

>>> a = [1, 2, 4]
>>> print a
[1, 2, 4]

>>> print a.insert(2, 3)
None

>>> print a
[1, 2, 3, 4]

>>> b = a.insert(3, 6)
>>> print b
None

>>> print a
[1, 2, 3, 6, 4]

Existe uma maneira de obter a lista atualizada como resultado, em vez de atualizar a lista original no local?

ATOzTOA
fonte
11
b = a[:].insert(2,3)parece bem curto, não afeta a lista original e é bem descritivo.
mkoistinen
6
@mkoistinen Não funciona para mim. >>> a = [1, 2, 3, 4] >>> b = a[:].insert(2, 5) >>> print b None
SparkAndShine

Respostas:

89

l.insert(index, obj)não retorna nada. Ele apenas atualiza a lista.

Como disse o ATO, você pode fazer b = a[:index] + [obj] + a[index:]. No entanto, outra maneira é:

a = [1, 2, 4]
b = a[:]
b.insert(2, 3)
Rushy Panchal
fonte
56
Se você não pode tolerar 3 linhas de código legível, coloque-o em uma função e chame-o.
IceArdor 01 de
54

Abordagem de desempenho mais eficiente

Você também pode inserir o elemento usando a indexação de fatias na lista. Por exemplo:

>>> a = [1, 2, 4]
>>> insert_at = 2  # Index at which you want to insert item

>>> b = a[:]   # Created copy of list "a" as "b".
               # Skip this step if you are ok with modifying the original list

>>> b[insert_at:insert_at] = [3]  # Insert "3" within "b"
>>> b
[1, 2, 3, 4]

Para inserir vários elementos juntos em um determinado índice , tudo o que você precisa fazer é usar um listdos vários elementos que deseja inserir. Por exemplo:

>>> a = [1, 2, 4]
>>> insert_at = 2   # Index starting from which multiple elements will be inserted

# List of elements that you want to insert together at "index_at" (above) position
>>> insert_elements = [3, 5, 6]

>>> a[insert_at:insert_at] = insert_elements
>>> a   # [3, 5, 6] are inserted together in `a` starting at index "2"
[1, 2, 3, 5, 6, 4]

Alternativa de compreensão de lista (mas muito lenta em termos de desempenho) :

Como alternativa, isso pode ser alcançado usando a compreensão de lista com enumeratetambém. (Mas, por favor, não faça assim. É apenas para ilustração) :

>>> a = [1, 2, 4]
>>> insert_at = 2

>>> b = [y for i, x in enumerate(a) for y in ((3, x) if i == insert_at else (x, ))]
>>> b
[1, 2, 3, 4]

Comparação de desempenho de todas as soluções

Aqui está a timeitcomparação de todas as respostas com a lista de 1000 elementos para Python 3.4.5:

  • Minha resposta usando inserção fatiada - Mais rápido (3,08 µs por loop)

     mquadri$ python3 -m timeit -s "a = list(range(1000))" "b = a[:]; b[500:500] = [3]"
     100000 loops, best of 3: 3.08 µsec per loop
  • Resposta aceita pela ATOzTOA com base na fusão de listas fatiadas - Segundo (6,71 µs por loop)

     mquadri$ python3 -m timeit -s "a = list(range(1000))" "b = a[:500] + [3] + a[500:]"
     100000 loops, best of 3: 6.71 µsec per loop
  • Resposta de Rushy Panchal com mais votos usandolist.insert(...)- Terceiro (26,5 usec por loop)

     python3 -m timeit -s "a = list(range(1000))" "b = a[:]; b.insert(500, 3)"
     10000 loops, best of 3: 26.5 µsec per loop
  • Minha resposta com Compreensão de lista eenumerate- Quarto (muito lento com 168 µs por loop)

     mquadri$ python3 -m timeit -s "a = list(range(1000))" "[y for i, x in enumerate(a) for y in ((3, x) if i == 500 else (x, )) ]"
     10000 loops, best of 3: 168 µsec per loop
Moinuddin Quadri
fonte
2
Eu realmente gosto deste resultado porque ele se estende facilmente para resolver o problema, e se eu quiser inserir os valores 3, 3.5nessa lista (na ordem) -> a[2:2] = [3,3.5]. Muito legal
minillinim de
1
Como funciona a [2: 2] = a_list? a [2: 2] está basicamente começando do 2º índice para o 1º índice (2-1), mas na direção para frente, o que significa uma lista [] vazia. Como isso se estende? Se fizermos [2: 3: -1], não funcionará.
SamCodes
Ótima resposta. Eu me pergunto se a complexidade da melhor escolha é O (1)? Se sim, por quê?
Lerner Zhang
Esta resposta precisa ser atualizada. Pela primeira vez, não consigo reproduzir os tempos relatados, mesmo com Python 3.4 (recebo um fator 2 entre uma list.insertatribuição de fatia) e no Python 3.8 essa diferença desapareceu completamente. A maneira mais clara de inserir um elemento é usando list.insert, obviamente.
a_guest
39

O mais curto que consegui: b = a[:2] + [3] + a[2:]

>>>
>>> a = [1, 2, 4]
>>> print a
[1, 2, 4]
>>> b = a[:2] + [3] + a[2:]
>>> print a
[1, 2, 4]
>>> print b
[1, 2, 3, 4]
ATOzTOA
fonte
O número de linhas de código não é uma boa medida da qualidade do código. Essa abordagem é falha por motivos de desempenho e legibilidade.
a_guest
0

A abordagem mais limpa é copiar a lista e inserir o objeto na cópia. No Python 3, isso pode ser feito por meio de list.copy:

new = old.copy()
new.insert(index, value)

No Python 2, a cópia da lista pode ser feita via new = old[:](isso também funciona no Python 3).

Em termos de desempenho, não há diferença para outros métodos propostos:

$ python --version
Python 3.8.1
$ python -m timeit -s "a = list(range(1000))" "b = a.copy(); b.insert(500, 3)"
100000 loops, best of 5: 2.84 µsec per loop
$ python -m timeit -s "a = list(range(1000))" "b = a.copy(); b[500:500] = (3,)"
100000 loops, best of 5: 2.76 µsec per loop
um convidado
fonte
-1

Use o método insert () da lista do Python . Uso:

#Sintaxe

A sintaxe para o método insert () -

list.insert(index, obj)

#Parameters

  • index - Este é o índice onde o objeto obj precisa ser inserido.
  • obj - Este é o objeto a ser inserido na lista fornecida.

#Return Value Este método não retorna nenhum valor, mas insere o elemento fornecido no índice fornecido.

Exemplo:

a = [1,2,4,5]

a.insert(2,3)

print(a)

Devoluções [1, 2, 3, 4, 5]

Arjun Sanchala
fonte
2
Isso não responde à pergunta.
Gustav Bertram
5
A pergunta era específica: Is there anyway I can get the updated list as result, instead of updating the original list in place?sua resposta faz o oposto.
Laszlowaty