Как проверить, соответствуют ли все элементы списка условию?

У меня есть список, состоящий из примерно 20000 списков. Я использую каждый список 3-й элемент в качестве флага. Я хочу сделать некоторые операции в этом списке, если хотя бы один флаг элемента равен 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 цикла, и она потребляет много времени! У вас есть какие-нибудь предложения?

Ответ 1

Лучший ответ здесь - использовать all(), который является встроенным для этой ситуации. Мы комбинируем это с выражением генератора , чтобы получить результат, который вы хотите чисто и эффективно. Например:

>>> items = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
>>> all(item[2] == 0 for item in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(item[2] == 0 for item in items)
False

А для примера с фильтром понимается список:

>>> [x for x in items if x[2] == 0]
[[1, 2, 0], [1, 2, 0]]

Если вы хотите проверить, что хотя бы один элемент равен 0, лучшим вариантом является использование any(), которое более читаемо:

>>> any(item[2] == 0 for item in items)
True

Ответ 2

Вы можете использовать itertools takewhile, как это, он остановится, как только будет выполнено условие, которое не приведет к вашему утверждению. Противоположный метод будет выпадать

for x in itertools.takewhile(lambda x: x[2] == 0, list)
    print x

Ответ 3

Если вы хотите проверить, что какой-либо элемент в списке нарушает условие, используйте all:

if all([x[2] == 0 for x in lista]):
    # Will run if all elements in the list has x[2] = 0 (use not to invert if necessary)

Чтобы удалить все несоответствующие элементы, используйте filter

# Will remove all elements where x[2] is 0
listb = filter(lambda x: x[2] != 0, listb)

Ответ 4

этот способ немного более гибкий, чем использование all():

my_list = [[1, 2, 0], [1, 2, 0], [1, 2, 0]]
all_zeros = False if False in [x[2] == 0 for x in my_list] else True
any_zeros = True if True in [x[2] == 0 for x in my_list] else False

или более кратко:

all_zeros = not False in [x[2] == 0 for x in my_list]
any_zeros = 0 in [x[2] for x in my_list]

Ответ 5

Другой способ использования itertools.ifilter. Это проверяет правдивость и процесс (используя lambda)

Пример -

for x in itertools.ifilter(lambda x: x[2] == 0, my_list):
    print x