我已经看到了一些关于列表展平的问题,我想知道如何检索展平列表的长度而不实际展平它。我的清单可以任意深入。
输入:
[[[1, 2], 3], 4]
输出:
4
输入:
[[[[1, 2], [3, 4]], 5], [6, 7]]
输出:
7
这是一个递归实现:
def flattenlen(a):
total = 0
for i in range(len(a)):
if type(a[i]) == list:
total += flattenlen(a[i])
else:
total += 1
return total
print flattenlen([[[[1, 2], [3, 4]], 5], [6, 7]])
输出:
7
有没有人有封闭式解决方案?是否有内置方法或库来实现这一目标?我错过了一种更有效的方法吗?
答案 0 :(得分:1)
您无需构建单独的列表即可轻松完成此操作:
def flattenlen(a):
return sum(flattenlen(i) if isinstance(i, list) else 1 for i in a)
这总结了列表的递归调用的结果,其余的单个1
值,所有这些都在一个生成器表达式循环中。
对于非递归版本,请使用堆栈:
def flattenlen(a):
total = 0
stack = [a]
while stack:
lst = stack.pop()
for i in lst:
if isinstance(i, list):
stack.append(i)
else:
total += 1
return total
要获得更完整的解决方案,请使用collections.Iterable
和basestring
来测试任何非字符串(unicode
或str
)的可迭代对象:
from collections import Iterable
_typetest = lambda t: isinstance(t, Iterable) and not isinstance(t, basestring)
def flattenlen(a):
return sum(flattenlen(i) if _typetest(i) else 1 for i in a)
演示:
>>> from collections import Iterable
>>> _typetest = lambda t: isinstance(t, Iterable) and not isinstance(t, basestring)
>>> def flattenlen(a):
... return sum(flattenlen(i) if _typetest(i) else 1 for i in a)
...
>>> flattenlen([[[[1, 2], [3, 4]], 5], [6, 7]])
7
>>> flattenlen([([[1, 2], [3, 4]], 5), {6, 7, 'foobar'}])
8