У меня есть список, состоящий из примерно 20000 списков. Я использую третий элемент каждого списка в качестве флага. Я хочу сделать некоторые операции в этом списке, если хотя бы один из элементов флага равен 0, это похоже на:
my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]
В начале все флаги равны 0. Я использую цикл while, чтобы проверить, равен ли хотя бы один элемент 0:
def check(list_):
for item in list_:
if item[2] == 0:
return True
return False
Если check(my_list)
возвращается True
, то я продолжаю работать над своим списком:
while check(my_list):
for item in my_list:
if condition:
item[2] = 1
else:
do_sth()
На самом деле, я хотел удалить элемент в my_list при его итерации по нему, но мне не разрешено удалять элементы при его итерации по нему.
Оригинальный my_list не имел флагов:
my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]
Поскольку я не мог удалить элементы, пока я перебирал их, я изобрел эти флаги. Но он my_list
содержит много элементов, и while
цикл читает все из них в каждом for
цикле, и это занимает много времени! Есть ли у вас какие-либо предложения?
источник
None
или[]
когда вы перебираете список вместо того, чтобы удалять их. Проверка всего списка с помощью 'check () `итерации по всем элементам перед каждым проходом во внутреннем цикле - очень медленный подход.Ответы:
Лучший ответ здесь - это использование
all()
, встроенное в эту ситуацию. Мы объединяем это с выражением генератора, чтобы получить результат, который вы хотите, чисто и эффективно. Например:Обратите внимание, что
all(flag == 0 for (_, _, flag) in items)
это прямо эквивалентноall(item[2] == 0 for item in items)
, в данном случае читать немного приятнее.И, для примера фильтра, понимание списка (конечно, вы можете использовать выражение генератора, где это уместно):
Если вы хотите проверить, что хотя бы один элемент равен 0, лучше использовать
any()
более читаемый:источник
all()
иany()
короткое замыкание, если, например, первое значение на моем будет оценено какFalse
,all()
потерпит неудачу и не проверит больше значений, возвращаяFalse
. Ваш пример будет делать то же самое, за исключением того, что сначала будет сгенерирован весь список сравнений, что означает большую обработку для ничего.Если вы хотите проверить, нарушает ли какой-либо элемент в списке условие, используйте
all
:Чтобы удалить все элементы, не соответствующие, используйте
filter
источник
[...]
в ,all(...)
так как это может создать генератор вместо списка, который не только экономит вам два символа , но и экономит память и время. При использовании генераторов будет рассчитываться только один элемент за раз (прежние результаты будут отбрасываться, так как больше не используются), и, если какой-либо из них окажетсяFalse
, генератор прекратит вычислять остальные.Вы можете использовать команду itertools следующим образом: она остановится, как только будет выполнено условие, которое не соответствует вашему утверждению. Противоположный метод будет в то же время
источник
Еще один способ использования
itertools.ifilter
. Это проверяет правдивость и процесс (используяlambda
)Образец-
источник
этот способ немного более гибкий, чем использование
all()
:или более кратко:
источник
all_zeros = False in [x[2] == 0 for x in my_list]
или даже0 in [x[2] for x in my_list]
и соответственно дляany_zeros
? Я не вижу заметного улучшения по сравнению с этимall()
.all_zeros = False in [x[2] == 0 for x in my_list]
оцениваетFalse
, а моя -True
. Если вы измените его наall_zeros = not (False in [x[2] == 0 for x in my_list])
то, что эквивалентно моему. И0 in [x[2] for x in my_list]
, очевидно, только собирается работатьany_zeros
. Но мне нравится краткость вашей идеи, поэтому я