深度列表计数 - 列表中的列表计数
Deep list count - count lists within lists
我正在尝试获取列表的长度,但该列表可以包含其他深度嵌套的列表(例如 [[[[[[[]]]]]]]
)。
但是您还必须在计数中获取任何非列表元素:[1, 2, [3, 4]]
将输出 5(1、2、3、4 和一个列表)。 ["a", "b", ["c", "d", ["e"]]]
会输出 7。
首先想到的是用递归来解决这个问题。
我写了这个:
def deep_count(arr, count=0):
if any(type(i) == list for i in arr):
for i in arr:
if type(i) == list:
count += len(arr)
else:
count += 1
return deep_count(arr[1:], count)
return count
它输出 9 而不是 7。如果它只是像 [[[]]]
这样的嵌套列表,它只输出 1。
在谈论递归时,请始终考虑基本情况(不会进行递归的情况)。在您的问题中,当列表为空时,它将 return 计数为 0。
所以你可以像这样开始实施它:
def f(arr):
if arr == []:
return 0
对于实施的其余部分,您有两种方法:
- 遍历列表,当它实际上是一个子列表时将
f(sublist)
添加到计数中,如果不是 则添加 1
- 完全递归并始终调用
f(x)
函数,无论它是否是子列表,并且始终将结果添加到计数中。在这种情况下,您有一个新的基本情况,其中 f(not_a_list)
将 return 1
我想这应该会让你解脱
注意:我刚读到不需要递归,你想出了它。我认为这是解决此类问题的好方法
class Counter:
def __init__(self):
self.counter = 0
def count_elements(self, l):
for el in l:
if type(el) == list:
self.counter += 1
self.count_elements(el)
else:
self.counter += 1
l = ["a", "b", ["c", "d", ["e"]]]
c = Counter()
c.count_elements(l)
print(c.counter)
似乎不需要提供初始值,您可以只使用 arr
作为唯一参数,然后只获取计数,如果当前元素是列表,则还添加该列表的计数。
def f(arr):
count = len(arr)
for element in arr:
if isinstance(element, list):
count += f(element)
return count
>>> f([1, 2, [3, 4]])
5
>>> f(["a", "b", ["c", "d", ["e"]]])
7
递归添加所有列表长度(Try it online!):
def f(xs):
return len(xs) + sum(f(x) for x in xs
if isinstance(x, list))
变体(Try it online!):
def f(xs):
return isinstance(xs, list) and len(xs) + sum(map(f, xs))
我的旧答案将 OP 的最后一个示例的结果作为预期输出。如果不考虑,答案很简单:
>>> def count_deep_list(lst):
... return sum(count_deep_list(val) for val in lst if isinstance(val, list)) + len(lst)
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
2
旧答案:
看来你需要对内部空列表和传入列表本身进行特殊判断。我觉得需要借助闭包来实现:
>>> def count_deep_list(lst):
... def count(_lst):
... if isinstance(_lst, list):
... if not _lst:
... return 0
... else:
... return sum(map(count, _lst)) + 1
... else:
... return 1
...
... return count(lst) - 1 if lst else 0
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
1
更简单的实现:
>>> def count_deep_list(lst):
... def count(_lst):
... return sum(count(val) if val else -1 for val in _lst if isinstance(val, list)) + len(_lst)
... return count(lst) if lst else 0
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
1
双行答案为:
def lenrecursive(seq):
return len(seq) + sum(lenrecursive(s) for s in seq if isinstance(s,Sized) and not isinstance(s, str))
但是这不会考虑到其他东西可能有 len
使用 EAPF 方法的更完整处理是:
def lenrecursive(seq):
"""
Returns total summed length of all elements recursively.
If no elements support len then return will be 0, no TypeError will be raised
"""
def _len(x):
try:
return len(x)
except TypeError: #no len
return 0
try:
return _len(seq) + sum(lenrecursive(s) for s in seq if not isinstance(s, str))
except TypeError: #not iterable
return _len(seq)
备注:
- 为什么
not isinstance(s, str)
? - 字符串将导致无限递归,因为 one-character 字符串是一个序列,因此 lenrecursive(a)
会 return 1 + lenrecursive(a)
即 1 + 1 + lenrecursive(a)
即 1 + 1 + 1 + ...
- 为什么 EAFP 使用
try: except:
而不是使用 isinstance
检查 LBYL? - 因为那里有很多支持 len
的东西,你不知道下次调用它时是否创建了一个自定义 class,它有一个 __len__
但没有't subclass Sequence
、Mapping
或继承自 collections.Sized
的其他内容
我正在尝试获取列表的长度,但该列表可以包含其他深度嵌套的列表(例如 [[[[[[[]]]]]]]
)。
但是您还必须在计数中获取任何非列表元素:[1, 2, [3, 4]]
将输出 5(1、2、3、4 和一个列表)。 ["a", "b", ["c", "d", ["e"]]]
会输出 7。
首先想到的是用递归来解决这个问题。 我写了这个:
def deep_count(arr, count=0):
if any(type(i) == list for i in arr):
for i in arr:
if type(i) == list:
count += len(arr)
else:
count += 1
return deep_count(arr[1:], count)
return count
它输出 9 而不是 7。如果它只是像 [[[]]]
这样的嵌套列表,它只输出 1。
在谈论递归时,请始终考虑基本情况(不会进行递归的情况)。在您的问题中,当列表为空时,它将 return 计数为 0。
所以你可以像这样开始实施它:
def f(arr):
if arr == []:
return 0
对于实施的其余部分,您有两种方法:
- 遍历列表,当它实际上是一个子列表时将
f(sublist)
添加到计数中,如果不是 则添加 - 完全递归并始终调用
f(x)
函数,无论它是否是子列表,并且始终将结果添加到计数中。在这种情况下,您有一个新的基本情况,其中f(not_a_list)
将 return1
1
我想这应该会让你解脱
注意:我刚读到不需要递归,你想出了它。我认为这是解决此类问题的好方法
class Counter:
def __init__(self):
self.counter = 0
def count_elements(self, l):
for el in l:
if type(el) == list:
self.counter += 1
self.count_elements(el)
else:
self.counter += 1
l = ["a", "b", ["c", "d", ["e"]]]
c = Counter()
c.count_elements(l)
print(c.counter)
似乎不需要提供初始值,您可以只使用 arr
作为唯一参数,然后只获取计数,如果当前元素是列表,则还添加该列表的计数。
def f(arr):
count = len(arr)
for element in arr:
if isinstance(element, list):
count += f(element)
return count
>>> f([1, 2, [3, 4]])
5
>>> f(["a", "b", ["c", "d", ["e"]]])
7
递归添加所有列表长度(Try it online!):
def f(xs):
return len(xs) + sum(f(x) for x in xs
if isinstance(x, list))
变体(Try it online!):
def f(xs):
return isinstance(xs, list) and len(xs) + sum(map(f, xs))
我的旧答案将 OP 的最后一个示例的结果作为预期输出。如果不考虑,答案很简单:
>>> def count_deep_list(lst):
... return sum(count_deep_list(val) for val in lst if isinstance(val, list)) + len(lst)
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
2
旧答案:
看来你需要对内部空列表和传入列表本身进行特殊判断。我觉得需要借助闭包来实现:
>>> def count_deep_list(lst):
... def count(_lst):
... if isinstance(_lst, list):
... if not _lst:
... return 0
... else:
... return sum(map(count, _lst)) + 1
... else:
... return 1
...
... return count(lst) - 1 if lst else 0
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
1
更简单的实现:
>>> def count_deep_list(lst):
... def count(_lst):
... return sum(count(val) if val else -1 for val in _lst if isinstance(val, list)) + len(_lst)
... return count(lst) if lst else 0
...
>>> count_deep_list([1, 2, [3, 4]])
5
>>> count_deep_list(["a", "b", ["c", "d", ["e"]]])
7
>>> count_deep_list([[[]]])
1
双行答案为:
def lenrecursive(seq):
return len(seq) + sum(lenrecursive(s) for s in seq if isinstance(s,Sized) and not isinstance(s, str))
但是这不会考虑到其他东西可能有 len
使用 EAPF 方法的更完整处理是:
def lenrecursive(seq):
"""
Returns total summed length of all elements recursively.
If no elements support len then return will be 0, no TypeError will be raised
"""
def _len(x):
try:
return len(x)
except TypeError: #no len
return 0
try:
return _len(seq) + sum(lenrecursive(s) for s in seq if not isinstance(s, str))
except TypeError: #not iterable
return _len(seq)
备注:
- 为什么
not isinstance(s, str)
? - 字符串将导致无限递归,因为 one-character 字符串是一个序列,因此lenrecursive(a)
会 return1 + lenrecursive(a)
即1 + 1 + lenrecursive(a)
即1 + 1 + 1 + ...
- 为什么 EAFP 使用
try: except:
而不是使用isinstance
检查 LBYL? - 因为那里有很多支持len
的东西,你不知道下次调用它时是否创建了一个自定义 class,它有一个__len__
但没有't subclassSequence
、Mapping
或继承自collections.Sized
的其他内容