如何检查列表中的所有元素是否都符合条件?

问题:如何检查列表中的所有元素是否都符合条件?

我有一个包含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循环中读取所有项目,这会花费大量时间!你有什么建议吗?

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?


回答 0

最好的答案是使用all(),这是这种情况的内置函数。我们将其与生成器表达式结合使用,以干净高效地生成您想要的结果。例如:

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

请注意,all(flag == 0 for (_, _, flag) in items)它直接等效于all(item[2] == 0 for item in items),在这种情况下阅读起来要好一些。

并且,对于过滤器示例,使用列表推导(当然,可以在适当的地方使用生成器表达式):

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

如果要检查至少一个元素为0,则更好的选择是使用any()更具可读性的元素:

>>> any(flag == 0 for (_, _, flag) in items)
True

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(flag == 0 for (_, _, flag) in items)
True
>>> items = [[1, 2, 0], [1, 2, 1], [1, 2, 0]]
>>> all(flag == 0 for (_, _, flag) in items)
False

Note that all(flag == 0 for (_, _, flag) in items) is directly equivalent to all(item[2] == 0 for item in items), it’s just a little nicer to read in this case.

And, for the filter example, a list comprehension (of course, you could use a generator expression where appropriate):

>>> [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(flag == 0 for (_, _, flag) in items)
True

回答 1

如果要检查列表中的任何项目是否违反条件,请使用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)

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)

回答 2

您可以像这样使用itertools的takewhile,一旦满足条件会使您的语句失败,它将停止。相反的方法是dropwhile

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

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

回答 3

另一种使用方式itertools.ifilter。这会检查真实性和过程(使用lambda

样品-

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

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

回答 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]

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

or more succinctly:

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