質問

ヒストグラムを計算するPythonプログラムを作成する方法はたくさんあります。

ヒストグラムとは、オブジェクトの発生をカウントする関数を意味します iterable 辞書にカウントを出力します。例えば:

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

この関数を書く1つの方法は、次のとおりです。

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

この機能を書くためのより簡潔な方法はありますか?

Pythonで辞書の包括的な概念があった場合、次のことを書くことができます。

>>> { x: L.count(x) for x in set(L) }

しかし、Python 2.6にはそれらがないため、次のことを書く必要があります。

>>> dict([(x, L.count(x)) for x in set(L)])

このアプローチは読みやすいかもしれませんが、効率的ではありません。Lは複数回歩きます。さらに、これは単一生活ジェネレーターでは機能しません。関数は、次のようなイテレータージェネレーターでも同様にうまく機能するはずです。

def gen(L):
    for x in L:
        yield x

使用しようとするかもしれません reduce 関数(RIP):

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

おっと、これは機能しません:キー名は 'x', 、 いいえ x. :(

私は終わりました:

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

(Python 3では、書く必要があります list(d.items()) それ以外の d.items(), 、しかし、それは仮想的です、なぜならないので reduce そこの。)

より良い、より読みやすいワンライナーで私をbeatりましてください! ;)

役に立ちましたか?

解決

Python 3.xにはあります reduce, 、あなたはただしなければなりません from functools import reduce. 。また、「Dict Combensions」もあり、例にはまさに構文があります。

Python 2.7および3.xにもaがあります カウンター あなたが望むことを正確に行うクラス:

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

Python 2.6以前では、個人的に defaultdict そして、2行でそれを行います:

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

それはきれいで効率的で、ピトニックで、ほとんどの人にとっては何よりも理解しやすいです reduce.

他のヒント

Oneliners用のモジュールをインポートするのはちょっと不和なので、ここにO(n)であり、少なくともPython2.4まで遡るOnelinerがあります。

>>> 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}

そして、あなたが考えるなら __ 方法はハッキーで、いつでもこれを行うことができます

>>> 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}

:)

$d{$_} += 1 for split //, 'abracadabra';
import pandas as pd

pd.Series(list(L)).value_counts()

Python 2.7の場合、この小さなリストの理解を使用できます。

v = list('abracadabra')
print {x: v.count(x) for x in set(v)}

2.3に戻るもの(Timmermanよりもわずかに短く、読みやすいと思います):

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}

しばらくの間、何でも使用しています itertools 定義上、Pythonicでした。それでも、これは不透明な面に少しです:

>>> 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}

現在、Python 2.5.4を実行しています。

あなたのワンライナーを使用します reduce ほとんど大丈夫でした、あなたはそれを少し微調整する必要がありました:

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

もちろん、これはインプレースソリューション(スピードもパイソン性もありません)に勝るものではありませんが、それと引き換えに、純粋に機能的なスニペットを持っています。ところで、Pythonに方法があれば、これはややきれいです dict.merge().

Python 2.2で最大2.7で動作するためにヒストグラムの実装が必要で、これを思いつきました。

>>> 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}

私は、Eli CourtwrightのDefaultDictの投稿に触発されました。これらはPython 2.5で導入されたため、使用できません。しかし、それらはdict.setDefault(key、default)でエミュレートできます。

これは基本的にGnibblerがやっていることと同じですが、彼のLambda機能を完全に理解する前に、最初にこれを書かなければなりませんでした。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top