How to check if all elements of a list matches a condition?

I have a list consisting of like 20000 lists. I use each list's 3rd element as a flag. I want to do some operations on this list as long as at least one element's flag is 0, it's like:

my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]

In the beginning, all flags are 0. I use a while loop to check if at least one element's flag is 0:

def check(list_):
    for item in list_:
        if item[2] == 0:
            return True
    return False

If check(my_list) returns True, then I continue working on my list:

while check(my_list):
    for item in my_list:
        if condition:
            item[2] = 1
        else:
            do_sth()

Actually, I wanted to remove an element in my_list as I iterated over it, but I'm not allowed to remove items as I iterate over it.

Original my_list didn't have flags:

my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]

Since I couldn't remove elements as I iterated over it, I invented these flags. But the my_list contains many items, and while loop reads all of them at each for loop, and it consumes lots of time! Do you have any suggestions?

Answers


The best answer here is to use all(), which is the builtin for this situation. We combine this with a generator expression to produce the result you want cleanly and efficiently. For example:

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

And, for his filter example, a list comprehension:

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

If you want to check at least one element is 0, the better option is to use any() which is more readable:

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

You could use itertools's takewhile like this, it will stop once a condition is met that fails your statement. The opposite method would be dropwhile

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

If you want to check if any item in the list violates a condition use 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)

To remove all elements not matching, use filter

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

this way is a bit more flexible than using 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

Another way to use itertools.ifilter. This checks truthiness and process (using lambda)

Sample-

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

Need Your Help

How to write from Java to the Windows Event Log?

java windows logging event-log

How can I write from Java to the Windows Event Log?

Testing simple STI with FactoryGirl

ruby-on-rails ruby rspec factory-bot sti

I have got a class, that is the base of some other classes that specializes the behavior: