【问题标题】:Reduce list of list to dictionary with sublist size as keys and number of occurances as value将列表列表减少为字典,以子列表大小为键,出现次数为值
【发布时间】:2016-02-18 00:19:08
【问题描述】:

我有一个列表列表,我想计算具有特定大小的子列表出现的次数。

例如。对于列表[[1], [1,2], [1,2], [1,2,3]],我希望得到{1: 1, 2: 2, 3: 1}

我试过reduce 函数,但+= 1 有语法错误,不知道哪里出了问题。

list_of_list = [[1], [1,2], [1,2], [1,2,3]]
result = functools.reduce(lambda dict,list: dict[len(list)] += 1, list_of_list, defaultdict(lambda: 0, {}))

【问题讨论】:

  • 这不起作用的原因是因为您在 lambda 中分配值。在python中,赋值语句不能在lambda中使用。

标签: python dictionary lambda reduce


【解决方案1】:

当您可以以更 Pythonic 的方式使用 collections.Counter()map() 函数时,以如此复杂的方式使用 reduce 并不是一个好主意:

>>> A = [[1], [1,2], [1,2], [1,2,3]]
>>> from collections import Counter
>>> 
>>> Counter(map(len,A))
Counter({2: 2, 1: 1, 3: 1})

请注意,使用map 将比生成器表达式执行得稍好,因为通过将生成器表达式传递给Counter(),python 将自行从生成器函数中获取值,因为使用内置函数map 具有更高的性能在执行时间方面1.

~$ python -m timeit --setup "A = [[1], [1,2], [1,2], [1,2,3]];from collections import Counter" "Counter(map(len,A))"
100000 loops, best of 3: 4.7 usec per loop
~$ python -m timeit --setup "A = [[1], [1,2], [1,2], [1,2,3]];from collections import Counter" "Counter(len(x) for x in A)"
100000 loops, best of 3: 4.73 usec per loop

来自PEP 0289 -- Generator Expressions

生成器表达式的语义等价于创建匿名生成器函数并调用它。例如:

g = (x**2 for x in range(10))
print g.next()

相当于:

def __gen(exp):
    for x in exp:
        yield x**2
g = __gen(iter(range(10)))
print g.next()

请注意,由于 generator expression 在内存使用方面更好,如果您正在处理大数据,您最好使用 generator expression 而不是 map 功能。

【讨论】:

    【解决方案2】:

    您也可以使用Counter 来执行此操作:

    list_of_list = [[1], [1,2], [1,2], [1,2,3]]
    c = Counter(len(i) for i in list_of_list)
    

    输出:

    Counter({2: 2, 1: 1, 3: 1})
    

    【讨论】:

    • 吹毛求疵:Counter 构造函数中不需要中间列表,它可以接受生成器表达式:c = Counter(len(i) for i in list_of_list)
    【解决方案3】:

    reduce 是完成这项工作的劣质工具。

    改为查看collections.Counter。这是一个 dict 子类,所以你应该可以使用它,但是你打算使用 dict。

    >>> from collections import Counter
    >>> L = [[1], [1, 2], [1, 2], [1, 2, 3]]
    >>> Counter(len(x) for x in L)
    Counter({1: 1, 2: 2, 3: 1})
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-30
      • 2014-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      相关资源
      最近更新 更多