14

辞書内の最小値に対応するキーを取得するのと同じことをしようとしています 。ここで、辞書内の最小値に対応するキーを取得します。

最善の方法は次のように思われます。

min(d, key=d.get)

しかし、これを複数の最小値を持つ辞書に適用したいと思います。

d = {'a' : 1, 'b' : 2, 'c' : 1}

上記の答えは次のようになることに注意してください。

>>> min(d, key=d.get)
'a'

ただし、最小値を持つ2つのキー、つまりとの両方が必要です。ac

最善のアプローチは何でしょうか?

(最終的には、2つのうちの1つをランダムに選択したいのですが、これは適切ではないと思います)。

4

9 に答える 9

14

簡単なオプションの1つは、最初に最小値を決定してから、その最小値にマッピングされているすべてのキーを選択することです。

min_value = min(d.itervalues())
min_keys = [k for k in d if d[k] == min_value]

Python 3の場合d.values()は、の代わりに使用しd.itervalues()ます。

これには辞書を2回通過する必要がありますが、とにかくこれを行うための最速のオプションの1つであるはずです。

リザーバーサンプリングを使用すると、アイテムの1つをランダムに選択するシングルパスアプローチを実装できます。

it = d.iteritems()
min_key, min_value = next(it)
num_mins = 1
for k, v in it:
    if v < min_value:
        num_mins = 1
        min_key, min_value = k, v
    elif v == min_value:
        num_mins += 1
        if random.randrange(num_mins) == 0:
            min_key = k

このコードを書き留めた後、このオプションはかなり理論的に興味深いと思います…:)

于 2012-03-30T14:33:50.343 に答える
2

編集済み:提案どおりにsetdefaultを使用するようになりました:)

それがあなたに役立つかどうかはわかりませんが、キーとしての値と(値としてのリスト内の)キーを使用して逆引き辞書を作成することができます。

d = {'a' : 1, 'b' : 2, 'c' : 1}
d2 = {}
for k, v in d.iteritems():
    d2.setdefault(v, []).append(k)
print d2[min(d2)]

これを印刷します:

['a', 'c']

ただし、他のソリューションはよりコンパクトで、おそらくよりエレガントだと思います...

于 2012-03-30T14:39:55.703 に答える
1
min_keys = [k for k in d if all(d[m] >= d[k] for m in d)]

または、わずかに最適化

min_keys = [k for k, x in d.items() if not any(y < x for y in d.values())]

他のソリューションほど効率的ではありませんが、Pythonの美しさを示しています(少なくとも私にとっては)。

于 2012-03-30T14:46:08.740 に答える
0

1回のパスでそれを行う別の方法は次のとおりです。

d = {'foo': 2, 'a' : 1, 'b' : 2, 'c' : 1, 'z': 99, 'x': 1}
current_min = d[d.keys()[0]]
min_keys = []
for k, v in d.iteritems():
    if v < current_min:
        current_min = v
        min_keys = [k]
    elif v == current_min:
        min_keys.append(k)
print min_keys
['a', 'x', 'c']
于 2012-03-30T14:56:25.863 に答える
0
def get_rand_min(d):
    min_val = min(d.values())
    min_keys = filter(lambda k: d[k] == min_val, d)
    return random.choice(min_keys)
于 2012-03-30T14:35:49.050 に答える
0

heapq.nsmallestを使用して、dictのN個の最小メンバーを取得し、最も低いメンバーと等しくないものをすべて除外できます。それはあなたが持つことができる最小のメンバーの最大数を知っているという条件で、ここではそれがNであると仮定しましょう。何かのようなもの:

from heapq import nsmallest
from operator import itemgetter

#get the N smallest members
smallestN = nsmallest(N, myDict.iteritems(), itemgetter(1)))

#leave in only the ones with a score equal to the smallest one
smallest = [x for x in smallestN if x[1] == smallestN[0][1]]
于 2012-03-30T14:35:57.643 に答える
0

これは機能します:

d = {'a' :1, 'b' : 2, 'c' : 1}
min_value = min(d.values())
result = [x[0] for x in d.items() if x[1] == k]

Hmpf。コードを修正して機能させると、@ Sven Marnachの答えが返ってきたので、これは無視してください;)

于 2012-03-30T14:36:53.333 に答える
0
minValue,minKey = min((v,k) for k,v in d.items())

セマンティクスのため、辞書全体を少なくとも1回は調べる必要があります。これにより、最小要素が1つだけ取得されます。

O(log(N))クエリ時間のすべての最小項目が必要な場合は、要素を生成するときに、要素を優先キューに挿入できます(可能な場合)。優先キューには、O(1)挿入時間とO(log(N))抽出最小時間が必要です。(これは、すべての要素の値が同じである場合は並べ替えと同じくらい悪いですが、それ以外の場合は非常にうまく機能する可能性があります。)

于 2012-03-30T14:37:48.897 に答える
0

ワンパスソリューションは次のようになります。

 >>> result = [100000, []]
>>> for key, val in d.items():
...  if val < result[0]:
...   result[1] = [key]; result[0]=val;
...  elif val == result[0]:
...   result[1].append(key)
... 
>>> result
[1, ['a', 'c']]
于 2012-03-30T14:56:45.507 に答える