我对空列表的定义是:
a = []
a = [[], []]
a = [[], [], [[], []]]
通用方法不适用,因为最后两个列表的长度不为0,在if条件下,它们将被视为True。
if a:
print(True) # True
#-------------------------
print(len(a) != 0) # True
有什么好的检查方法吗?
答案 0 :(得分:2)
Kinda很傻,但可能是不错的解决方案:
if str(a).strip('[], '):
或者list
可能包含自身,并且应该算作空:
if str(a).strip('[], .'):
依靠这样一个事实,list
仅用方括号,空格和逗号来表示,但是它们包含的任何内容(没有故意引起病的repr
)都具有一些涉及的其他角色。包含自身的list
在递归时使用...
,因此剥离处理它们。因此,我们strip
仅出现在空白list
和空白list
的空白list
和list
中的唯一字符,如果还剩下任何内容,则表示存在非{{1 }}在那里。
答案 1 :(得分:1)
您可以使用一个功能来递归检查子列表中的项目:
def is_empty(l):
return all(is_empty(i) if isinstance(i, list) else False for i in l)
这样:
print(is_empty([[], [], [[], []]]))
print(is_empty([[], [], [[], [1]]]))
输出:
True
False
如果要处理包含循环引用的列表,则可以使用seen
集来跟踪该函数已看到的列表引用,并在看到它们时跳过它们:
def is_empty(l, seen=None):
if seen is None:
seen = set()
return all(seen.add(id(i)) or is_empty(i, seen) if isinstance(i, list) else False for i in l if id(i) not in seen)
这样:
a = []
a.append(a)
print(is_empty(a))
a = [1]
a.append(a)
print(is_empty(a))
输出:
True
False
答案 2 :(得分:0)
要检查每个项目,有一种简单但有用的方法。
In [65]: a = [[], [], [[], [1]]]
In [66]: mark = []
In [67]: def recursive_check(lst, mark):
...: for i in lst:
...: if isinstance(i, list):
...: recursive_check(i, mark)
...: else:
...: mark.append(i)
...: return mark
然后,您可以在调用recursive_check
recursive_check(a, mark)
,您可以轻松检查标记值,例如:
if mark:
pass
每次通话后,如果您在terminal
上运行,请不要忘记将mark
重置为空。
mark=[]
要使其易于使用,可以添加另一个函数对其进行包装。
In [77]: def test(lst):
...: mark = []
...: return len(recursive_check(lst, mark)) != 0
...:
In [78]: a
Out[78]: [[], [], [[], [1]]]
In [79]: test(a)
Out[79]: True
In [80]: cc
Out[80]: [[], [], [[], []]]
In [81]: test(cc)
Out[81]: False
答案 3 :(得分:0)
我认为您可能需要递归。试试这个:
def is_empty(arr, seen=None):
# Infinite loops detection
if seen is None:
seen = set()
if id(arr) in seen:
arr.remove(arr)
seen.add(id(arr))
if isinstance(arr, list):
if arr:
return all(is_empty(b, seen) for b in arr)
else:
return True
else:
return False
基本上,任何不是列表的内容都意味着您的列表不为空。如果找到非空列表,它将开始查找其中的每个元素。如果除了列表中还有任何元素,它将返回False
。
经过编辑以避免无限循环(感谢@MadPhysicist!)
答案 4 :(得分:0)
您需要的解决方案不仅要递归,还要防止无限递归。这是一种可能性:
def has_non_list(x):
""" Assumes x is a list """
seen = set() # stash IDs since lists aren't hashable
def check(x):
if id(x) in seen:
return False
seen.add(id(x))
for i in x:
if not isinstance(i, list) or check(i):
return True
return False
return check(x)
使此序列适用于任何序列应该很容易。
答案 5 :(得分:0)
更可组合/可重用的答案是使生成器函数展平嵌套的list
(或为提高可重用性,使用任意可迭代对象),从而使结果迭代变得微不足道;如果它产生任何东西,则它是非空的(并且您可以立即停止迭代,以节省list
中潜在的list
s上的工作),否则为空:>
def flatten(it, skip_same_list=True):
'''Returns a generator of all non-lists in possibly nested list
If skip_same_list is False, this will produce infinite output if a list is
nested inside itself'''
stack = [it]
seen = set()
while stack:
item = stack.pop()
if isinstance(item, list):
if skip_same_list:
if id(item) in seen:
continue # Ignores same list if seen again
seen.add(id(item))
stack.extend(reversed(item))
else:
yield item
有了这些,解决问题就变得微不足道了:
def my_is_empty(it, *, _sentinel=object()):
# Two arg next returns the first item or _sentinel if no items yielded
return next(flatten(it), _sentinel) is _sentinel
# Alternative without sentinel object:
def my_is_empty(it):
try:
next(flatten(it))
except StopIteration:
return True
return False
如果您想要任意嵌套的可迭代对象以提高适用性,而不仅仅是list
,则flatten
的代码会变得更加复杂,而my_is_empty
则保持不变。
与my other answer相比,这显然是更复杂的代码,但它也是非启发式的(因此,具有真正奇怪的repr
的类型不能欺骗它),可重复用于其他目的,并且当大多数输入为非空时,尤其是输入较大时,速度会更快(因为它会在发现非空状态确认后立即停止处理,而不会浪费时间list
上的其余时间)。>