简体   繁体   English

Python:如何检查嵌套列表是否本质上是空的?

[英]Python: How to check if a nested list is essentially empty?

Is there a Pythonic way to check if a list (a nested list with elements & lists) is essentially empty ?是否有一种 Pythonic 方法来检查列表(带有元素和列表的嵌套列表)是否本质上是空的 What I mean by empty here is that the list might have elements, but those are also empty lists.我在这里所说的空是指列表可能有元素,但那些也是空列表。

The Pythonic way to check an empty list works only on a flat list:检查空列表的 Pythonic 方法仅适用于平面列表:

alist = []
if not alist:
    print("Empty list!")

For example, all the following lists should be positive for emptiness:例如,以下所有列表都应该为空:

alist = []
blist = [alist]               # [[]]
clist = [alist, alist, alist] # [[], [], []]
dlist = [blist]               # [[[]]]

Use the any() function.使用any()函数。 This returns True if any list within the list is not empty.如果列表中的任何列表不为空,则返回True

alist = [[],[]]
if not any(alist):
    print("Empty list!")

>> Empty list!

see: https://www.programiz.com/python-programming/methods/built-in/any见: https : //www.programiz.com/python-programming/methods/built-in/any

I have combined the use of isinstance() by Ants Aasma and all(map()) by Stephan202 , to form the following solution.我结合了Ants Aasmaisinstance()Stephan202 的all(map())使用,形成了以下解决方案。 all([]) returns True and the function relies on this behaviour. all([])返回True并且该函数依赖于这种行为。 I think it has the best of both and is better since it does not rely on the TypeError exception.我认为它兼具两者的TypeError并且更好,因为它不依赖于TypeError异常。

def isListEmpty(inList):
    if isinstance(inList, list): # Is a list
        return all( map(isListEmpty, inList) )
    return False # Not a list

Simple code, works for any iterable object, not just lists:简单的代码,适用于任何可迭代对象,而不仅仅是列表:

>>> def empty(seq):
...     try:
...         return all(map(empty, seq))
...     except TypeError:
...         return False
...
>>> empty([])
True
>>> empty([4])
False
>>> empty([[]])
True
>>> empty([[], []])
True
>>> empty([[], [8]])
False
>>> empty([[], (False for _ in range(0))])
True
>>> empty([[], (False for _ in range(1))])
False
>>> empty([[], (True for _ in range(1))])
False

This code makes the assumption that anything that can be iterated over will contain other elements, and should not be considered a leaf in the "tree".此代码假设任何可以迭代的内容都将包含其他元素,不应将其视为“树”中的叶子。 If an attempt to iterate over an object fails, then it is not a sequence, and hence certainly not an empty sequence (thus False is returned).如果尝试迭代对象失败,则它不是序列,因此肯定不是空序列(因此返回False )。 Finally, this code makes use of the fact that all returns True if its argument is an empty sequence.最后,这段代码利用了这样一个事实:如果其参数是空序列,则all返回True

If you do not need to iterate through the lists, simpler is better, so something like this will work:如果您不需要遍历列表,则越简单越好,因此可以使用以下方法:

def empty_tree(input_list):
    """Recursively iterate through values in nested lists."""
    for item in input_list:
        if not isinstance(item, list) or not empty_tree(item):
             return False
    return True

However, it would be good to separate the recursive iteration that you will most probably reuse elsewhere and checking that it returns no elements.但是,最好将您最有可能在其他地方重用的递归迭代分开并检查它是否不返回任何元素。 This way if the mechanism of iteration changes you need to implement the change in one place.这样,如果迭代机制发生变化,您需要在一个地方实现更改。 For instance when you need to support arbitrary nested iterables, or nested dicts.例如,当您需要支持任意嵌套的可迭代对象或嵌套的字典时。

def flatten(input_list):
    """Recursively iterate through values in nested lists."""
    for item in input_list:
        if isinstance(item, list): # Use what ever nesting condition you need here
            for child_item in flatten(item):
                yield child_item
        else:
            yield item

def has_items(seq):
    """Checks if an iterator has any items."""
    return any(1 for _ in seq)

if not has_items(flatten(my_list)):
    pass

I don't think there is an obvious way to do it in Python.我认为在 Python 中没有明显的方法可以做到这一点。 My best guess would be to use a recursive function like this one :我最好的猜测是使用这样的递归函数:

def empty(li):
    if li == []:
        return True
    else:
        return all((isinstance(sli, list) and empty(sli)) for sli in li)

Note that all only comes with Python >= 2.5, and that it will not handle infinitely recursive lists (for example, a = []; a.append(a) ).请注意, all仅随 Python >= 2.5 提供,并且不会处理无限递归列表(例如, a = []; a.append(a) )。

A simple recursive check would be enough, and return as early as possible, we assume it input is not a list or contains non-lists it is not empty一个简单的递归检查就足够了,并尽可能早地返回,我们假设它输入不是列表或包含非列表它不为空

def isEmpty(alist):
    try:
        for a in alist:
            if not isEmpty(a):
                return False
    except:
        # we will reach here if alist is not a iterator/list
        return False

    return True

alist = []
blist = [alist]               # [[]]
clist = [alist, alist, alist] # [[], [], []]
dlist = [blist]               # [[[]]]
elist = [1, isEmpty, dlist]

if isEmpty(alist): 
    print "alist is empty"

if isEmpty(dlist): 
    print "dlist is empty"

if not isEmpty(elist): 
    print "elist is not empty"

You can further improve it to check for recursive list or no list objects, or may be empty dicts etc.您可以进一步改进它以检查递归列表或无列表对象,或者可能是空字典等。

def isEmpty(a):
    return all(map(isEmpty,a)) if isinstance(a, list) else False

Simply.简单地。

If you want to check if the nested list has no item in it, you can use a Depth First Search (DFS) traversing method like this如果要检查嵌套列表中是否没有项目,可以使用这样的深度优先搜索 (DFS) 遍历方法

def is_list_empty(values: list):
    
    if len(values) == 0:
        return True

    res = []
    for val in values:
        if isinstance(val, list):
            res.append(is_list_empty(val))
        else:
            res.append(False)
    
    return all(res)

v_list = [ [], [[1, 2], [], []], []]
is_list_empty(v_list)  # False, as there are two times in it.
v_list = [ [], [[], [], []], []]
is_list_empty(v_list)  # True, in fact ther is no item in it.

This is similar to @AshwinNanjappa's answer but it is easier to understand.这类似于@AshwinNanjappa 的回答,但更容易理解。

It is possible to check if a list of lists is empty or not by using len function to check if the list's length equal to zero or not, then use any to give True if there is any True (There is at least one empty sublist), as shown:可以通过使用len函数检查列表的长度是否等于零来检查列表列表是否为空,然后使用any给出True如果有任何True (至少有一个空子列表) , 如图所示:

def empty(lis):
    # True if there is an empty sublist
    x = [True for i in lis if len(i) == 0]
    # any function will return True if at least there is one True in x
    if any(x):
        print("There is an empty sublist!!")
    else:
        print("There is no any empty sublist")
        
lis = [[1,2,3],[3],[2]]
empty(lis)
# The output is: There is no any empty sublist
lis2 = [[1,2,3],[],[]]
empty(lis2)
# The output is: There is an empty sublist!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM