Hoe kan ik lijstitems wijzigen tijdens de for-lus?

Nu weet ik dat het niet veilig is om de lijst te wijzigen tijdens een iteratieve lus. Stel dat ik een lijst met snaren heb en ik wil de snaren zelf strippen. Telt vervanging van veranderlijke waarden als wijziging?


Antwoord 1, autoriteit 100%

Aangezien de onderstaande lus alleen elementen aanpast die al gezien zijn, wordt dit als acceptabel beschouwd:

a = ['a',' b', 'c ', ' d ']
for i, s in enumerate(a):
    a[i] = s.strip()
print(a) # -> ['a', 'b', 'c', 'd']

Wat anders is dan:

a[:] = [s.strip() for s in a]

in die zin dat er geen tijdelijke lijst hoeft te worden gemaakt en deze moet worden toegewezen om het origineel te vervangen, hoewel er wel meer indexeringsbewerkingen nodig zijn.

Let op:hoewel u items op deze manier kunt wijzigen, kunt u het aantal items in de listniet wijzigen zonder de kans te riskeren van problemen.

Hier is een voorbeeld van wat ik bedoel: het verwijderen van een item verstoort de indexering vanaf dat moment:

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!

(Het resultaat is fout omdat niet alle items zijn verwijderd.)

Bijwerken

Aangezien dit een redelijk populair antwoord is, kunt u als volgt items “ter plaatse” verwijderen (ook al is dat niet precies de vraag):

b = ['a',' b', 'c ', ' d ']
b[:] = [entry for entry in b if entry.strip() == entry]
print(b)  # -> ['a']  # CORRECT

Zie Hoe verwijder je items uit een lijst tijdens iteratie? .


Antwoord 2, autoriteit 76%

Het wordt als een slechte vorm beschouwd. Gebruik in plaats daarvan een lijstbegrip, met segmenttoewijzing als u bestaande verwijzingen naar de lijst wilt behouden.

a = [1, 3, 5]
b = a
a[:] = [x + 2 for x in a]
print(b)

Antwoord 3, autoriteit 12%

Nog een for-loop-variant, lijkt me schoner dan een met 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

Antwoord 4, autoriteit 7%

Het is prima om elk element aan te passen tijdens het herhalen van een lijst, zolang u het toevoegen/verwijderen van elementen aan de lijst niet wijzigt.

U kunt lijstbegrip gebruiken:

l = ['a', ' list', 'of ', ' string ']
l = [item.strip() for item in l]

of doe gewoon de C-stylefor loop:

for index, item in enumerate(l):
    l[index] = item.strip()

Antwoord 5, autoriteit 2%

Het antwoordvan Ignacio Vazquez-Abrams is echt goed. Het kan verder worden geïllustreerd aan de hand van dit voorbeeld. Stel je voor dat:

  1. U krijgt een lijst met twee vectoren.
  2. U wilt de lijst doorlopen en de volgorde van elk van de arrays omkeren.

Stel dat je het volgende hebt:

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

Je krijgt:

[array([1, 2, 3, 4]), array([3, 4, 6])]

Aan de andere kant, als u dat wel doet:

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

Het resultaat is:

[array([4, 3, 2, 1]), array([6, 4, 3])]

Antwoord 6, autoriteit 2%

Nee, je zou de “inhoud” van de lijst niet veranderen, als je strings op die manier zou kunnen muteren. Maar in Python zijn ze niet veranderlijk. Elke tekenreeksbewerking retourneert een nieuwe tekenreeks.

Als je een lijst met objecten had waarvan je wist dat ze veranderbaar waren, zou je dit kunnen doen zolang je de feitelijke inhoud van de lijst niet verandert.

Je zult dus een soort kaart moeten maken. Als u een generatoruitdrukking gebruikt, wordt [de bewerking] uitgevoerd terwijl u itereert en bespaart u geheugen.


Antwoord 7, autoriteit 2%

Je kunt zoiets als dit doen:

a = [1,2,3,4,5]
b = [i**2 for i in a]

Het wordt een lijstbegrip genoemd, zodat u gemakkelijker door een lijst kunt bladeren.


Antwoord 8

Het is niet duidelijk uit uw vraag wat de criteria zijn om te beslissen welke tekenreeksen u wilt verwijderen, maar als u een lijst heeft of kunt maken van de tekenreeksen die u wilt verwijderen, kunt u het volgende doen:

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)

die my_strings verandert in [‘a’, ‘c’, ‘e’]


Antwoord 9

Kortom, om de lijst te wijzigen terwijl dezelfde lijst wordt herhaald.

list[:] = ["Modify the list" for each_element in list "Condition Check"]

voorbeeld:

list[:] = [list.remove(each_element) for each_element in list if each_element in ["data1", "data2"]]

Other episodes