Я создал программу, в которой у меня есть список элементов: string, int и float. Я хотел удалить из списка элементы, которые не являются плавающими, или строки, в которых есть гласные.
mylist=['hey',20.0,'hey','hop',77,'orange',11,'yay',19,'hello','xyz','mop',11,30.5,90,'hat','on']
index=0
while (index<len(mylist)):
var=mylist[index]
if type(var) is int:
mylist.pop(index)
if type(var) is str:
i=0
while (i<len(var)):
char=var[i]
if (char=='a' or char=='e' or char=='i' or char=='u' or char=='o'):
mylist.pop(index)
i=i+1
index=index+1
print(mylist)
Все работает нормально - значения с плавающей запятой остаются нетронутыми, а значения int выталкиваются, но 1. каким-то образом элементы в определенных местах не выталкиваются из списка, даже если они являются целыми. 2. все строки проверяются нормально, но строки, содержащие только «o», каким-то образом обходят оператор pop. Где я ошибаюсь?
Кроме того, петля while выглядит неправильно — i=i+1 должна быть внутри петли.
Большое спасибо @slothrop! Цикл while был в порядке, просто опечатка, которую я сделал в посте. Детализация индекса действительно помогла мне: D






Основная проблема в вашем текущем коде заключается в том, что вы изменяете список, проходя по нему в цикле! В приведенном ниже коде я изменил его так, что у меня есть отдельный список, который будет результатом этого кода.
mylist=['hey', 20.0, 'hey', 'hop', 77, 'orange', 11, 'yay', 19, 'hello', 'xyz', 'mop', 11, 30.5, 90, 'hat', 'on']
newList = []
for var in mylist:
if type(var) is int:
continue
elif type(var) is str:
hasVowel = False
for char in var:
if (char in 'aeiou'):
hasVowel = True
break
if not hasVowel:
newList.append(var)
else:
newList.append(var)
print(newList)
Я заменил циклы while на циклы for, чтобы сделать код немного проще, поэтому я объясню код, если он кому-то понадобится.
Во-первых, я сохраняю ваш список, а затем создаю пустой список newList, который будет выводом. Затем я использую цикл for-each для перебора всех элементов в mylist. Если текущий элемент var имеет тип int, то я просто перехожу к следующему элементу, если он имеет тип str, я перебираю все символы в var и проверяю, являются ли какие-либо из них a, e, i, o или u. Если они есть, я использую переменную hasVowel, чтобы отметить, что в текущем var есть гласные. После этого я проверяю эту переменную и, если это False, я добавляю текущую var к newList. Наконец, если var любого другого типа (не int или str), я просто добавляю его к newList.
Если вы хотите, чтобы в конце кода были применены все изменения к mylist, вы можете добавить эту строку кода:
mylist = list(newList)
Причина, по которой я использую list() вместо того, чтобы просто установить его равным newList, заключается в том, что в случае, если какие-либо изменения будут внесены в newList позже в коде, это не повлияет на mylist.
Надеюсь это поможет :)
Спасибо! Хотя я не хотел создавать новый список, а хотел внести изменения только в тот же список. Ваше решение помогло мне исправить мое!
Я добавил дополнительную строку кода, чтобы при необходимости изменить исходный список!
Он игнорирует что-либо в индексе сразу после того, что вы удалили, потому что вы увеличиваете index, даже когда вы выталкиваете что-то из списка (фактически пропуская следующее в индексе). Проблема только в игнорировании строк, содержащих букву o, потому что по совпадению эти строки находятся в этих слепых зонах в вашем списке.
Рассмотрим следующий код, предназначенный для удаления четных чисел из списка:
Ваш подход (всегда увеличивающийся индекс)
a = [0,0,1,1,2,2,3,3,4,4]
i = 0
while(i < len(a)):
v = a[i]
if ( v % 2 == 0):
a.pop(i) # yeet if even
# always increment i
i += 1
print("outcome from always incrementing i")
print(*a) # 0 1 1 2 3 3 4 (incorrect)
Правильный подход
b = [0,0,1,1,2,2,3,3,4,4]
i = 0
while (i < len(b)):
v = b[i]
if (v % 2 == 0):
b.pop(i) # yeet current if even
else:
# only increment 'i' if we are not yeeting it
i += 1
print ("outcome from only incrementing i if not popping")
print(*b) # 1 1 3 3 (correct)
Итак, если вы настроите свой код только на увеличение index, не удаляя элементы из списка, ваш код должен начать работать, как задумано.
Большое спасибо! Работал на меня
Это крайне неэффективно. Просто используйте понимание списка и назначьте его исходной переменной списка. b = [n вместо n в b, если n % 2] Также... "пока"?
@DarkKnight Намерение состояло в том, чтобы помочь OP понять, почему их код не работает, заменив их код на MRE. Конечно, это может быть «ужасно неэффективный» способ удаления четных чисел из списка, но «просто показать OP понимание списка этого упрощенного MRE» не помогло бы.
Никогда не изменяйте список, который вы повторяете. В зависимости от того, что именно вы делаете, это может работать или не работать.
В этом случае нет необходимости изменять исходный список. Просто напишите функцию, которая определяет, является ли элемент в списке обязательным (или нет). Затем используйте понимание списка, чтобы создать новый список. Дискретная функция делает понимание списка менее громоздким.
Что-то вроде этого:
VOWELS = set('aeiouAEIOU')
def keep(v):
match v:
case float():
return True
case str():
return not any(c in VOWELS for c in v)
case _:
return False
mylist = ['hey', 20.0, 'hey', 'hop', 77, 'orange', 11, 'yay', 19, 'hello', 'xyz', 'mop', 11, 30.5, 90, 'hat', 'on']
newlist = [e for e in mylist if keep(e)]
print(newlist)
Выход:
[20.0, 'xyz', 30.5]
Спасибо! Хотя я не хотел создавать новый список, а хотел внести изменения только в тот же список. Ваше решение помогло мне исправить мое!
@SuhaniGurjar Итак, вместо создания нового списка просто назначьте понимание списка mylist. Это будет значительно эффективнее, чем изменение списка на месте.
Или сделайте mylist[:] = newlist, чтобы изменить объект, на который ссылается mylist (вместо переназначения), чтобы любая другая часть программы со ссылкой на mylist увидела изменение.
Вы увеличиваете
index = index + 1каждый раз во внешнем цикле, но это приводит к тому, что вы пропускаете элементы. Допустим, вы начинаете с int10с индексом 0 и int42с индексом 1. На первой итерации ваш код выталкивается10из списка, поэтому42перемещается к индексу 0. Но на следующей итерацииindexравно 1, и так далее.42никогда не обрабатывается. См.: stackoverflow.com/questions/1207406/…