python histogram one-liner

前端 未结 9 936
一生所求
一生所求 2020-12-02 09:10

There are many ways to write a Python program that computes a histogram.

By histogram, I mean a function that counts the occurrence of objects in an iterable

相关标签:
9条回答
  • 2020-12-02 09:15

    I needed a histogram implementation to work in python 2.2 up to 2.7, and came up with this:

    >>> L = 'abracadabra'
    >>> hist = {}
    >>> for x in L: hist[x] = hist.setdefault(x,0)+1
    >>> print hist
    {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}
    

    I was inspired by Eli Courtwright's post of a defaultdict. These were introduced in python 2.5 so can't be used. But they can be emulated with the dict.setdefault(key,default).

    This is basically the same thing gnibbler is doing, but I had to write this first before I could completely understand his lambda function.

    0 讨论(0)
  • 2020-12-02 09:19

    Your one-liner using reduce was almost ok, you only needed to tweak it a little bit:

    >>> reduce(lambda d, x: dict(d, **{x: d.get(x, 0) + 1}), L, {})
    {'a': 5, 'b': 2, 'c': 1, 'd': 1, 'r': 2}
    

    Of course, this won't beat in-place solutions (nor in speed, nor in pythonicity), but in exchange you've got yourself a nice purely functional snippet. BTW, this would be somewhat prettier if Python had a method dict.merge().

    0 讨论(0)
  • 2020-12-02 09:27

    One that works back to 2.3 (slightly shorter than Timmerman's, I think more readable) :

    L = 'abracadabra'
    hist = {}
    for x in L: hist[x] = hist.pop(x,0) + 1
    print hist
    {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1}
    
    0 讨论(0)
  • 2020-12-02 09:31

    Python 3.x does have reduce, you just have to do a from functools import reduce. It also has "dict comprehensions", which have exactly the syntax in your example.

    Python 2.7 and 3.x also have a Counter class which does exactly what you want:

    from collections import Counter
    cnt = Counter("abracadabra")
    

    In Python 2.6 or earlier, I'd personally use a defaultdict and do it in 2 lines:

    d = defaultdict(int)
    for x in xs: d[x] += 1
    

    That's clean, efficient, Pythonic, and much easier for most people to understand than anything involving reduce.

    0 讨论(0)
  • 2020-12-02 09:31

    For a while there, anything using itertools was by definition Pythonic. Still, this is a bit on the opaque side:

    >>> from itertools import groupby
    >>> grouplen = lambda grp : sum(1 for i in grp)
    >>> hist = dict((a[0], grouplen(a[1])) for a in groupby(sorted("ABRACADABRA")))
    >>> print hist
    {'A': 5, 'R': 2, 'C': 1, 'B': 2, 'D': 1}
    

    I'm currently running Python 2.5.4.

    0 讨论(0)
  • 2020-12-02 09:32

    For python 2.7, you can use this small list comprehension:

    v = list('abracadabra')
    print {x: v.count(x) for x in set(v)}
    
    0 讨论(0)
提交回复
热议问题