2

嗨,我有一个 python 问题,我必须在具有不同嵌套级别的列表中计算哪些列表元素包含值 2。例如:

my_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]

这个列表最多可以有三层嵌套,但也可以是两层或只有一层。

我有一段代码可以工作:

count = 0
for i in my_list:
    if len(i) > 1:
        for x in i:
            if 2 in x:
                count += 1
    elif i == 2:
        count += 1

然而,除了非常丑陋之外,这并没有考虑到有一个包含单个元素 2 的列表的可能性。获得len()单个int.

我知道列表理解应该能够解决这个问题,但我对如何处理潜在的嵌套有点坚持。

任何帮助将非常感激。

4

3 回答 3

7

我会使用flatten()来自https://stackoverflow.com/a/2158532/367273的生成器的变体

原始版本从任意嵌套和不规则形状的迭代结构中产生每个元素。我的变体(如下)产生最内层的迭代而不是产生标量。

from collections import Iterable

def flatten(l):
    for el in l:
        if isinstance(el, Iterable) and any(isinstance(subel, Iterable) for subel in el):
            for sub in flatten(el):
                yield sub
        else:
            yield el

my_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]
print(sum(1 for el in flatten(my_list) if 2 in el))

对于您的示例,它会打印3.

于 2012-12-10T20:17:16.747 回答
0

更新和最终答案:

我的解决方案递归了一个嵌套的列表列表。如果列表包含2,则计数设置为 1。然后添加任何子列表的计数总和。这种方法支持异构列表,其中数字和列表可以在同一级别混合,如下面的第二个使用示例所示:

import collections

def list_count(l):
    count = int(2 in l)
    for el in l:
        if isinstance(el, collections.Iterable):
            count += list_count(el)
    return count

这里有几个测试用例:

my_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]
print = list_count(my_list)
# 3 is printed

my_list = [2, [2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]
print = list_count(my_list)
# 4 is printed

@Akavall 的回答提醒我这可以折叠成单行。(但是当我这样做时,我总是会收到(通常是合理的)关于 SO 的可读性投诉。)

def list_count(l):
    return ( int(2 in l) +
        sum([list_count(el) for el in l 
            if isinstance(el, collections.Iterable)]) )

原始答案(不是原始问题要寻找的)

更新:@NPE 在指定预期结果后更新了他的答案。他目前的答案符合原始海报的要求。

@NPE 的(原始)答案很接近,但您问:

计算哪些列表元素包含值 2

我根据您的需要阅读:

my_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]
print(sum([1 for e in [flatten(sl) for sl in ml] if 2 in e]))

但他正在寻找3。我的代码生成 2,因为它遍历每个顶级元素并计算它是否包含任何 2,但这不是他真正想要的。

于 2012-12-10T20:29:24.230 回答
0

这是另一种方法:

small_list = [2]
my_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1]]
another_list = [[2,3,2,2], [[2,1,2,1], [2,1,1]], [1,1,1], 2]

from collections import Iterable 

def count_lists_w_two(x):
    if isinstance(x, Iterable) == False:
        return 0
    else:
        return (2 in x) + sum(count_lists_w_two(ele) for ele in x)

结果:

>>> count_lists_w_two(small_list)
1
>>> count_lists_w_two(my_list)
3
>>> count_lists_w_two(another_list)
4
于 2012-12-10T21:25:26.713 回答