Agora eu sei que não é seguro modificar a lista durante um loop iterativo. No entanto, suponha que eu tenha uma lista de seqüências de caracteres e que eu queira desmontá-las. A substituição de valores mutáveis conta como modificação?
Agora eu sei que não é seguro modificar a lista durante um loop iterativo. No entanto, suponha que eu tenha uma lista de seqüências de caracteres e que eu queira desmontá-las. A substituição de valores mutáveis conta como modificação?
Respostas:
É considerado uma forma ruim. Em vez disso, use uma compreensão de lista, com atribuição de fatia, se precisar manter as referências existentes na lista.
a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)
print b
instrução é executada, você pode dizer se a
foi modificado no local e não substituído. Outra possibilidade seria print b is a
verificar se os dois ainda se referem ao mesmo objeto.
Como o loop abaixo modifica apenas os elementos já vistos, seria considerado aceitável:
a = ['a',' b', 'c ', ' d ']
for i, s in enumerate(a):
a[i] = s.strip()
print(a) # -> ['a', 'b', 'c', 'd']
O que é diferente de:
a[:] = [s.strip() for s in a]
na medida em que não requer a criação de uma lista temporária e uma atribuição para substituir a original, embora exija mais operações de indexação.
Cuidado: Embora você possa modificar as entradas dessa maneira, não é possível alterar o número de itens list
sem arriscar a chance de encontrar problemas.
Aqui está um exemplo do que quero dizer - excluir uma entrada atrapalha a indexação a partir desse ponto:
b = ['a', ' b', 'c ', ' d ']
for i, s in enumerate(b):
if s.strip() != b[i]: # leading or trailing whitespace?
del b[i]
print(b) # -> ['a', 'c '] # WRONG!
(O resultado está errado porque não excluiu todos os itens que deveria ter.)
Atualizar
Como esta é uma resposta bastante popular, veja como excluir efetivamente as entradas "no local" (mesmo que essa não seja exatamente a pergunta):
b = ['a',' b', 'c ', ' d ']
b[:] = [entry for entry in b if entry.strip() == entry]
print(b) # -> ['a'] # CORRECT
for i in a
? Isso é muito contra-intuitivo, aparentemente diferente de outros idiomas e resultou em erros no meu código que eu tive que depurar por um longo período de tempo. O Tutorial do Python nem sequer menciona isso. Embora deva haver alguma razão para isso?
a[i]
e s
) para o mesmo objeto na mesma linha quando você não precisa? Eu prefiro fazer a[i] = a[i].strip()
.
a[i] = s.strip()
apenas uma operação de indexação.
enumerate(b)
faz uma operação de indexação em cada iteração e você faz outra a[i] =
. AFAIK é impossível implementar esse loop em Python com apenas 1 operação de indexação por iteração de loop :(
Mais uma variante de loop, para mim parece mais limpa do que uma com enumerate ():
for idx in range(len(list)):
list[idx]=... # set a new value
# some other code which doesn't let you use a list comprehension
range(len(list))
no Python um cheiro de código.
enumerate
é um gerador, não está criando uma lista. De tuplas, ele as cria uma de cada vez, conforme itera na lista. A única maneira de dizer qual é mais lento seria timeit
.
Modificar cada elemento durante a iteração de uma lista é bom, desde que você não altere a adição / remoção de elementos na lista.
Você pode usar a compreensão da lista:
l = ['a', ' list', 'of ', ' string ']
l = [item.strip() for item in l]
ou apenas faça o C-style
loop for:
for index, item in enumerate(l):
l[index] = item.strip()
Não, você não alteraria o "conteúdo" da lista, se pudesse modificar as strings dessa maneira. Mas em Python eles não são mutáveis. Qualquer operação de string retorna uma nova string.
Se você tivesse uma lista de objetos que sabia que eram mutáveis, poderá fazer isso desde que não altere o conteúdo real da lista.
Assim, você precisará fazer um mapa de algum tipo. Se você usar uma expressão geradora, a [operação] será feita conforme você itera e você economiza memória.
A resposta de Jemshit Iskenderov e Ignacio Vazquez-Abrams é realmente boa. Pode ser ilustrado com este exemplo: imagine que
a) Uma lista com dois vetores é fornecida a você;
b) você gostaria de percorrer a lista e reverter a ordem de cada uma das matrizes
Digamos que você tenha
v = np.array([1, 2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i = i[::-1] # this command does not reverse the string
print([v,b])
Você vai ter
[array([1, 2, 3, 4]), array([3, 4, 6])]
Por outro lado, se você fizer
v = np.array([1, 2,3,4])
b = np.array([3,4,6])
for i in [v, b]:
i[:] = i[::-1] # this command reverses the string
print([v,b])
O resultado é
[array([4, 3, 2, 1]), array([6, 4, 3])]
Não está claro na sua pergunta quais são os critérios para decidir quais seqüências de caracteres remover, mas se você tiver ou puder fazer uma lista das cadeias que deseja remover, faça o seguinte:
my_strings = ['a','b','c','d','e']
undesirable_strings = ['b','d']
for undesirable_string in undesirable_strings:
for i in range(my_strings.count(undesirable_string)):
my_strings.remove(undesirable_string)
que altera minhas_strings para ['a', 'c', 'e']
Em resumo, fazer modificações na lista enquanto itera a mesma lista.
list[:] = ["Modify the list" for each_element in list "Condition Check"]
exemplo:
list[:] = [list.remove(each_element) for each_element in list if each_element in ["data1", "data2"]]