Python-dictから最初のN個のキーと値のペアを返します


108

次の辞書dを考えてみます。

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

最初のN個のキーと値のペアをdから返したい(この場合はN <= 4)。これを行う最も効率的な方法は何ですか?


1
注意。回答には多くの誤った情報があるようです。私のテストでは、単一のソリューションがよりも速くないことを示していlist(d.items())[:4]ます。list()は多くの回答の基礎となる実装です。
BSalita

回答:


114

a dictは最初に挿入されたキーを覚えていないので、「最初のn」キーはありません。

ただし n個のキーと値のペアを取得できます。

n_items = take(n, d.iteritems())

これは、レシピtakefrom の実装を使用しitertoolsます

from itertools import islice

def take(n, iterable):
    "Return first n items of the iterable as a list"
    return list(islice(iterable, n))

オンラインで動作することを確認してください:ideone


Python 3.6の更新

n_items = take(n, d.items())

42
私はPython 3の人たちにとってiteritems代わるべきだと思いますitems
モニカヘドネック2017

1
@MonicaHeddneck、素晴らしい、このコメントを追加してくれてありがとう。
Karl Baker

12
ここで初心者take()-Pythonコードベースの一部はどこにありますか?それとも、ここで回答で定義した純粋な関数ですか?それがコードベースの一部であるかのように尋ねると、それを見つけたりインポートしたりできません。:)
スコットボーデン

80

何かを検索する非常に効率的な方法は、リストまたは辞書の内包表記とスライスを組み合わせることです。アイテムを注文する必要がない場合(n個のランダムなペアが必要なだけ)、次のような辞書内包を使用できます。

# Python 2
first2pairs = {k: mydict[k] for k in mydict.keys()[:2]}
# Python 3
first2pairs = {k: mydict[k] for k in list(mydict)[:2]}

一般に、このような理解は、同等の「for x in y」ループよりも常に実行が高速です。また、.keys()を使用してディクショナリキーのリストを作成し、そのリストをスライスすることで、新しいディクショナリを構築するときに不要なキーに「触れる」ことを回避できます。

キー(値のみ)が必要ない場合は、リスト内包表記を使用できます。

first2vals = [v for v in mydict.values()[:2]]

キーに基づいて値をソートする必要がある場合は、それほど問題ではありません。

first2vals = [mydict[k] for k in sorted(mydict.keys())[:2]]

または、キーも必要な場合:

first2pairs = {k: mydict[k] for k in sorted(mydict.keys())[:2]}

2
リストではなくディクショナリとしてN個のキーと値のペアを選択する場合、これはより良いソリューションです
fermat4214

1
@ fermat4214これらのコマンドのいずれかを実行すると、辞書全体が印刷される場合、問題ですか?
テッドテイラーオブライフ

list(mydict)[:2]は、辞書をソートする必要がなく、最初の2つの要素のみが必要な場合は無駄です。辞書に1 mil kvのペアがある場合はどうなりますか?全体をリストに変換するにはコストがかかります。Mark Byersのソリューションははるかに優れています。
JJ

これは解決策です!
Guenter

14

Pythonのdictは順序付けされていないため、「最初のN」キーを要求しても意味がありません。

それcollections.OrderedDictが必要な場合は、クラスを利用できます。最初の4つの要素を効率的に取得できます。

import itertools
import collections

d = collections.OrderedDict((('foo', 'bar'), (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')))
x = itertools.islice(d.items(), 0, 4)

for key, value in x:
    print key, value

itertools.isliceイテレータから要素のスライスを遅延して取得できます。結果を再利用可能にしたい場合は、次のようにリストまたは何かに変換する必要があります。

x = list(itertools.islice(d.items(), 0, 4))

怠惰に見えません。`list(d.items())[:4]より2倍長くかかる
BSalita

12
foo = {'a':1, 'b':2, 'c':3, 'd':4, 'e':5, 'f':6}
iterator = iter(foo.items())
for i in range(3):
    print(next(iterator))

基本的には、ビュー(dict_items)をイテレータにしてから、next()で繰り返します。


2
素晴らしい答えです。これは、このページで私にとって効果的で読みやすい唯一の答えです。また、これがPython 3で動作することを確認できます。これは、以前の回答の一部には表示されないようです。
cdahms 2018

7

ここでは見ませんでした。辞書からいくつかの要素を取得する必要がある場合は、順序付けはされませんが、構文的には最も単純です。

n = 2
{key:value for key,value in d.items()[0:n]}

7
コードを試してみましたが、このエラーが発生しました:TypeError: 'dict_items' object is not subscriptable {key:value for key,value in stocks.items()[0:n]} (stocksは私の辞書の名前です)
Moondra

2
@Moondra-辞書項目を実行する前にリストに変換する必要があります。上記のコードでは、{key:value for key、value in list(d.items())[0:n]}の場合、行は機能します
Rajesh Mappu

{A:N for(A、N)in [x for x in d.items()] [:4]}
farid khafizov

6

Python辞書から上位N個の要素を取得するには、次のコード行を使用できます。

list(dictionaryName.items())[:N]

あなたの場合、それを次のように変更できます:

list(d.items())[:4]

3

PEP 0265を参照辞書のソートを。次に、前述の反復可能なコードを使用します。

ソートされたキーと値のペアでさらに効率が必要な場合。別のデータ構造を使用してください。つまり、ソートされた順序とキーと値の関連付けを維持するものです。

例えば

import bisect

kvlist = [('a', 1), ('b', 2), ('c', 3), ('e', 5)]
bisect.insort_left(kvlist, ('d', 4))

print kvlist # [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]



1

これは、あなたのケースで何が「最も効率的」かによって異なります。

巨大な辞書の半ランダムなサンプルが必要なだけで、そこから必要な数の値をfoo使用foo.iteritems()して取得する場合、これはキーまたはアイテムの明示的なリストの作成を回避する遅延操作です。

最初にキーをソートする必要がある場合は、keys = foo.keys(); keys.sort()またはのようなものを使用する方法がないsorted(foo.iterkeys())ため、キーの明示的なリストを作成する必要があります。次に、最初のNをスライスまたは反復します。keysます。

ところで、なぜ「効率的な」方法を気にするのですか?プログラムのプロファイルを作成しましたか?そうでない場合は、最初に明白わかりやすい方法使用してください。ボトルネックになることなく、かなりうまくいく可能性があります。


これは金融プログラムへのアプリケーションであり、コードのすべての行をできるだけ効率的に構築するようにしています。私はプログラムのプロファイルを作成しませんでしたが、これはおそらくボトルネックにならないことに同意しますが、デフォルトで効率的な解決策を求めたいと思います。返信いただきありがとうございます。
Jason Strimpel

0

これにはいくつかの方法でアプローチできます。順序が重要な場合、これを行うことができます:

for key in sorted(d.keys()):
  item = d.pop(key)

注文が気にならなければ、これを行うことができます:

for i in range(4):
  item = d.popitem()

最初のスニペットvalueではitem、わかりやすくするためではなく、おそらくそれを呼び出す必要があります。
agf

0

辞書は順序を維持しないため、上位N個のキーと値のペアを選択する前に、並べ替えることができます。

import operator
d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
#itemgetter(0)=sort by keys, itemgetter(1)=sort by values

これで、次のようなメソッド構造を使用して、上位の「N」要素の取得を実行できます。

def return_top(elements,dictionary_element):
    '''Takes the dictionary and the 'N' elements needed in return
    '''
    topers={}
    for h,i in enumerate(dictionary_element):
        if h<elements:
            topers.update({i:dictionary_element[i]})
    return topers

上位2つの要素を取得するには、次の構造を使用します。

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4}
d=dict(sorted(d.items(),key=operator.itemgetter(1),reverse=True))
d=return_top(2,d)
print(d)

0

Python 3以降の場合、最初のnペアを選択するには

n=4
firstNpairs = {k: Diction[k] for k in list(Diction.keys())[:n]}

0

口述を考える

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

from itertools import islice
n = 3
list(islice(d.items(),n))

isliceはトリックを行います:)それが役に立てば幸いです!


0

これはあまりエレガントではないかもしれませんが、私にとってはうまくいきます:

d = {'a': 3, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

x= 0
for key, val in d.items():
    if x == 2:
        break
    else:
        x += 1
        # Do something with the first two key-value pairs

0

上記の回答のいくつかを試してみましたが、それらの一部はバージョンに依存しており、バージョン3.7では機能しないことに注意してください。

また、3.6以降、すべての辞書はアイテムが挿入される順序で並べられていることに注意してください。

辞書は3.6以降で順序付けされていますが、順序付けられた構造で動作すると予想される一部のステートメントは動作しないようです。

私にとって最も効果的なOP質問への回答。

itr = iter(dic.items())
lst = [next(itr) for i in range(3)]

lst = list(d.items())[:N]
参考
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.