python直方图单行

myk*_*hal 47 python reduce counting histogram

有很多方法可以编写计算直方图的Python程序.

通过直方图,我的意思是一个函数,它计算a中对象的出现次数iterable并输出字典中的计数.例如:

>>> L = 'abracadabra'
>>> histogram(L)
{'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r': 2}
Run Code Online (Sandbox Code Playgroud)

编写此函数的一种方法是:

def histogram(L):
    d = {}
    for x in L:
        if x in d:
            d[x] += 1
        else:
            d[x] = 1
    return d
Run Code Online (Sandbox Code Playgroud)

是否有更简洁的方法来编写此功能?

如果我们在Python中有字典理解,我们可以写:

>>> { x: L.count(x) for x in set(L) }
Run Code Online (Sandbox Code Playgroud)

但由于Python 2.6没有它们,我们必须写:

>>> dict([(x, L.count(x)) for x in set(L)])
Run Code Online (Sandbox Code Playgroud)

虽然这种方法可以读取,但效率不高:L经过多次.此外,这对单寿命发电机不起作用; 该函数应该对迭代器生成器同样有效,例如:

def gen(L):
    for x in L:
        yield x
Run Code Online (Sandbox Code Playgroud)

我们可能会尝试使用该reduce函数(RIP):

>>> reduce(lambda d,x: dict(d, x=d.get(x,0)+1), L, {}) # wrong!
Run Code Online (Sandbox Code Playgroud)

糟糕,这不起作用:关键名称'x'不是x.:(

我结束了:

>>> reduce(lambda d,x: dict(d.items() + [(x, d.get(x, 0)+1)]), L, {})
Run Code Online (Sandbox Code Playgroud)

(在Python 3中,我们必须编写list(d.items())而不是d.items(),但它是假设的,因为没有reduce.)

请用更好,更易阅读的单行打败我!;)

Eli*_*ght 76

Python 3.x确实有reduce,你只需要做一个from functools import reduce.它还具有"dict comprehensions",它在您的示例中具有完全相同的语法.

Python 2.7和3.x也有一个Counter类,它可以完全符合你的要求:

from collections import Counter
cnt = Counter("abracadabra")
Run Code Online (Sandbox Code Playgroud)

在Python 2.6或更早版本中,我个人使用defaultdict并在2行中执行:

d = defaultdict(int)
for x in xs: d[x] += 1
Run Code Online (Sandbox Code Playgroud)

这是干净,高效,Pythonic,并且比大多数人更容易理解reduce.

  • Python 2.7也有dict理解. (4认同)

Joh*_*ooy 7

为oneliner导入模块有点讨厌,所以这里有一个O(n)的oneliner并且至少可以用于Python2.4.

>>> f=lambda s,d={}:([d.__setitem__(i,d.get(i,0)+1) for i in s],d)[-1]
>>> f("ABRACADABRA")
{'A': 5, 'R': 2, 'B': 2, 'C': 1, 'D': 1}
Run Code Online (Sandbox Code Playgroud)

如果你认为__方法很糟糕,你可以随时做到这一点

>>> f=lambda s,d=lambda:0:vars(([setattr(d,i,getattr(d,i,0)+1) for i in s],d)[-1])
>>> f("ABRACADABRA")
{'A': 5, 'R': 2, 'B': 2, 'C': 1, 'D': 1}
Run Code Online (Sandbox Code Playgroud)

:)


小智 6

$d{$_} += 1 for split //, 'abracadabra';
Run Code Online (Sandbox Code Playgroud)

  • @perl我认为你应该进一步采用这个新颖的帐户 (2认同)

小智 6

import pandas as pd

pd.Series(list(L)).value_counts()
Run Code Online (Sandbox Code Playgroud)


小智 5

对于python 2.7,您可以使用这个小列表理解:

v = list('abracadabra')
print {x: v.count(x) for x in set(v)}
Run Code Online (Sandbox Code Playgroud)