嵌套列表和 count()

Posted

技术标签:

【中文标题】嵌套列表和 count()【英文标题】:Nested List and count() 【发布时间】:2011-08-15 05:57:15 【问题描述】:

我想获取 x 在嵌套列表中出现的次数。

如果列表是:

list = [1, 2, 1, 1, 4]
list.count(1)
>>3

没关系。但如果列表是:

list = [[1, 2, 3],[1, 1, 1]]

如何获取 1 出现的次数?在这种情况下,4.

【问题讨论】:

先展平。到处搜索。 相关:Counting occurences in an arbitrarily nested list 【参考方案1】:

试试这个:

reduce(lambda x,y: x+y,list,[]).count(1)

基本上,您从一个空列表 [] 开始,然后将列表 list 的每个元素添加到其中。在这种情况下,元素本身就是列表,您会得到一个扁平列表。

PS:刚刚在另一个问题中的类似答案被否决了!

PPS:这个解决方案也被否决了!

【讨论】:

人们在这里任意投票。对糟糕的解决方案投反对票。我的绝对不是。并且没有提到提到的任意嵌套并且适用于 OP 的情况。不要想太多。 是的,因为您拒绝进一步思考,拒绝深入了解更深层次的问题以及如何找到更通用的解决方案。 .. 说在 Google 上搜索的人是这样说的。 很好的答案。谁在乎@AndreasJung 说什么。答案符合问题。【参考方案2】:

itertoolscollections 模块得到了你需要的东西(使用 itertools.chain 展平嵌套列表并使用 collections.Counter 计数

import itertools, collections

data = [[1,2,3],[1,1,1]]
counter = collections.Counter(itertools.chain(*data))
print counter[1]

使用递归展平函数而不是itertools.chain 展平任意级别深度的嵌套列表

import operator, collections

def flatten(lst):
    return reduce(operator.iadd, (flatten(i) if isinstance(i, collections.Sequence) else [i] for i in lst))

reduceoperator.iadd 已被使用而不是 sum,因此扁平化只构建一次并就地更新

【讨论】:

【参考方案3】:
>>> L = [[1, 2, 3], [1, 1, 1]]
>>> sum(x.count(1) for x in L)
4

【讨论】:

为什么人们不赞成非常有效的答案。我为此给出了+1,并且比我的回答更喜欢它。但我的回答并不糟糕,而且绝对不是这个!!! @manojlds, @Thomas:不要理会巨魔。鉴于 OP 的要求,这是一个完全有效的答案。 这是我见过的最好的答案。谢谢! 我们为什么使用 sum :( 请解释一下。【参考方案4】:

如果只有一层嵌套扁平化可以用这个列表压缩来完成:

>>> L = [[1,2,3],[1,1,1]]
>>> [ item for sublist in L for item in sublist ].count(1)
4
>>> 

【讨论】:

简单易行。【参考方案5】:

最重要的是:计数到任意嵌套深度,处理元组、列表和参数:

hits = lambda num, *n: ((1 if e == num else 0)
    for a in n
        for e in (hits(num, *a) if isinstance(a, (tuple, list)) else (a,)))

lst = [[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]]
print sum(hits(1, lst, 1, 1, 1))

15

【讨论】:

+1 为这里最酷的lambda 施虐者 ;-)。这也回答了如何在自身中递归嵌入生成器的问题:-)。【参考方案6】:
def nested_count(lst, x):
    return lst.count(x) + sum(
        nested_count(l,x) for l in lst if isinstance(l,list))

此函数返回出现次数,加上所有包含的子列表中的递归嵌套计数。

>>> data = [[1,2,3],[1,1,[1,1]]]
>>> print nested_count(data, 1)
5

【讨论】:

【参考方案7】:

这是另一种扁平化嵌套序列的方法。一旦序列被展平,就很容易找到项目的数量。

def flatten(seq, container=None):
    if container is None:
        container = []

    for s in seq:
        try:
            iter(s)  # check if it's iterable
        except TypeError:
            container.append(s)
        else:
            flatten(s, container)

    return container


c = flatten([(1,2),(3,4),(5,[6,7,['a','b']]),['c','d',('e',['f','g','h'])]])
print(c)
print(c.count('g'))

d = flatten([[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]])
print(d)
print(d.count(1))

以上代码打印:

[1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
12

【讨论】:

这个例子让我的内核崩溃了。 这会导致堆栈溢出,因为像'a' 这样的字符串实际上是可迭代的。这意味着它将继续调用递归。 hmm 我有点尴尬,我在很久以前(9 年)发布了这段代码,通常我会在发布之前运行并测试我的代码。现在,当我同时检查 python/2.7 和 python/3.7 时,上面的代码崩溃了。所以不确定上面的代码是否在我运行上面代码的python解释器中崩溃(我不记得它是什么版本),如果iter的行为在版本之间发生了变化,或者我发布的代码是错误的我发布的那天,错误仍未被发现。【参考方案8】:

以下函数将通过向结果输出列表添加非列表并递归处理列表来展平任何深度的列表(a)

def flatten(listOrItem, result = None):
    if result is None: result = []      # Ensure initial result empty.

    if type(listOrItem) != type([]):    # Handle non-list by appending.
        result.append(listOrItem)
    else:
        for item in listOrItem:         # Recursively handle each item in a list.
            flatten(item, result)
    return result                       # Return flattened container.

mylist = flatten([[1,2],[3,'a'],[5,[6,7,[8,9]]],[10,'a',[11,[12,13,14]]]])
print(f'Flat list is mylist, count of "a" is mylist.count("a")')

print(flatten(7))

一旦你有了一个扁平化的列表,使用count 就很简单了。 该代码的输出是:

Flat list is [1, 2, 3, 'a', 5, 6, 7, 8, 9, 10, 'a', 11, 12, 13, 14], count of "a" is 2
[7]

如果您不传递实际列表,请注意行为,它假定您无论如何都想要一个列表,一个仅包含单个项目的列表。


如果您不想要构造一个扁平列表,您可以使用类似的方法来获取列表列表中任何项目的计数,例如:

def deepCount(listOrItem, searchFor):
    if type(listOrItem) != type([]): # Non-list, one only if equal.
        return 1 if listOrItem == searchFor else 0

    subCount = 0                     # List, recursively collect each count.
    for item in listOrItem:
        subCount += deepCount(item, searchFor)
    return subCount

deepList = [[1,2],[3,'a'],[5,[6,7,[8,9]]],[10,'a',[11,[12,13,14]]]]
print(f'Count of "a" is deepCount(deepList, "a")')
print(f'Count of 13  is deepCount(deepList, 13)')
print(f'Count of 99  is deepCount(deepList, 99)')

正如预期的那样,这个输出是:

Count of "a" is 2
Count of 13  is 1
Count of 99  is 0

(a) 当然,在 Python 本身施加的限制范围内,您可以通过将其添加到代码顶部来增加限制:

import sys
sys.setrecursionlimit(1001) # I believe default is 1000.

我提到,在 case 中,你有一些非常深刻的嵌套结构,但你不应该真的需要它。如果你嵌套得那么深,那么你可能做错了什么:-)

【讨论】:

以上是关于嵌套列表和 count()的主要内容,如果未能解决你的问题,请参考以下文章

弹性搜索如何索引嵌套列表

嵌套字典。合并公共键并将值附加到列表中。 0 值未附加。里面的代码

Eloquent Count 嵌套关系与嵌套预加载

Mysql 聚合函数嵌套使用

为啥 .Select 或 .ToList() 提供嵌套 JSON,而 .Count 在父 JSON 中出现?

将嵌套的键/值和嵌套列表合并到 json