49

私はPython3.2.2に取り組んでいます。キーで辞書を並べ替えるために3時間以上頭を壊しました。なんとか2つの引数メンバーを持つソート済みリストにすることができましたが、最終的にはソート済み辞書にすることができません。

これは私が考え出したものです:

myDic={10: 'b', 3:'a', 5:'c'}
sorted_list=sorted(myDic.items(), key=lambda x: x[0])

しかし、このソートされたリストから辞書を作成することはできません。それ、どうやったら出来るの?ありがとう!

4

12 に答える 12

57

Python3.7向けの最新の高速ソリューション。Python3.6の一部のインタープリターでも機能する可能性があります。

TLDR

キーで辞書を並べ替えるには、次を使用します。

sorted_dict = {k: disordered[k] for k in sorted(disordered)}

受け入れられた答えよりもほぼ3倍速い。インポートを含めると、おそらくもっと多くなります。

受け入れられた回答にコメントする

キーのみを反復処理する代わりに、受け入れられた回答の例(dict反復のkeyパラメーターまたはデフォルトの動作を使用)はタプルを反復処理します。これは、キーのみを比較してリスト内包内の辞書要素にアクセスするよりも驚くほど遅いことがわかります。 。sorted()(key, value)

Python3.7でキーで並べ替える方法

Python 3.7での大きな変更は、辞書がデフォルトで順序付けられるようになったことです

  • dict内包表記を使用してソートされたdictを生成できます。
  • OrderedDict互換性のために、使用する方が望ましい場合があります。
  • sorted(d.items())なしで使用しないでくださいkey

見る:

disordered = {10: 'b', 3: 'a', 5: 'c'}

# sort keys, then get values from original - fast
sorted_dict = {k: disordered[k] for k in sorted(disordered)}

# key = itemgetter - slower
from operator import itemgetter
key = itemgetter(0)
sorted_dict = {k: v for k, v in sorted(disordered.items(), key=key)}

# key = lambda - the slowest
key = lambda item: item[0]
sorted_dict = {k: v for k in sorted(disordered.items(), key=key)} 

タイミング結果

Best for {k: d[k] for k in sorted(d)}: 7.507327548999456
Best for {k: v for k, v in sorted(d.items(), key=key_getter)}: 12.031082626002899
Best for {k: v for k, v in sorted(d.items(), key=key_lambda)}: 14.22885995300021

Best for dict(sorted(d.items(), key=key_getter)): 11.209122000000207
Best for dict(sorted(d.items(), key=key_lambda)): 13.289728325995384
Best for dict(sorted(d.items())): 14.231471302999125

Best for OrderedDict(sorted(d.items(), key=key_getter)): 16.609151654003654
Best for OrderedDict(sorted(d.items(), key=key_lambda)): 18.52622927199991
Best for OrderedDict(sorted(d.items())): 19.436101284998585

テストコード:

from timeit import repeat

setup_code = """
from operator import itemgetter
from collections import OrderedDict
import random
random.seed(0)
d = {i: chr(i) for i in [random.randint(0, 120) for repeat in range(120)]}
key_getter = itemgetter(0)
key_lambda = lambda item: item[0]
"""

cases = [
    # fast
    '{k: d[k] for k in sorted(d)}',
    '{k: v for k, v in sorted(d.items(), key=key_getter)}',
    '{k: v for k, v in sorted(d.items(), key=key_lambda)}',
    # slower
    'dict(sorted(d.items(), key=key_getter))',
    'dict(sorted(d.items(), key=key_lambda))',
    'dict(sorted(d.items()))',
    # the slowest 
    'OrderedDict(sorted(d.items(), key=key_getter))',
    'OrderedDict(sorted(d.items(), key=key_lambda))',
    'OrderedDict(sorted(d.items()))',
]

for code in cases:
    times = repeat(code, setup=setup_code, repeat=3)
    print(f"Best for {code}: {min(times)}")
于 2018-03-06T16:43:20.080 に答える
50

dict要素の順序を保持しません。必要なのはOrderedDictです:http://docs.python.org/library/collections.html#collections.OrderedDict

編集

使用例:

>>> from collections import OrderedDict
>>> a = {'foo': 1, 'bar': 2}
>>> a
{'foo': 1, 'bar': 2}
>>> b = OrderedDict(sorted(a.items()))
>>> b
OrderedDict([('bar', 2), ('foo', 1)])
>>> b['foo']
1
>>> b['bar']
2
于 2012-06-18T19:29:58.617 に答える
18

OrderedDictは必要ないと思います。ソートされた順序でキーを維持するdictであるSortedDictを好むようです。sortedcontainersモジュールは、まさにそのようなデータ型を提供します。それは純粋なPythonで書かれており、Cとしての高速な実装であり、100%のカバレッジと何時間ものストレスがあります。

インストールはpipで簡単です:

pip install sortedcontainers

それができない場合はpip install、オープンソースリポジトリからソースファイルをプルするだけでよいことに注意してください。

次に、コードは単純です。

from sortedcontainers import SortedDict
myDic = SortedDict({10: 'b', 3:'a', 5:'c'})
sorted_list = list(myDic.keys())

sortedcontainersモジュールは、他の一般的な実装とのパフォーマンス比較も維持します。

于 2014-09-23T06:41:28.630 に答える
11

Pythonの通常のdicts方法では、キー/要素を特定の順序で提供することはできません。そのためには、モジュールのOrderedDictタイプを使用できます。タイプは単に挿入順序の記録を保持するcollectionsことに注意してください。OrderedDict後続のビュー/イテレータが毎回要素を順番に返すようにする場合は、ディクショナリを初期化する前にエントリを並べ替える必要があります。例えば:

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sorted_list=sorted(myDic.items(), key=lambda x: x[0])
>>> myOrdDic = OrderedDict(sorted_list)
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> myOrdDic[7] = 'd'
>>> myOrdDic.items()
[(3, 'a'), (5, 'c'), (10, 'b'), (7, 'd')]

新しく追加されたアイテムの適切な順序を維持したい場合は、実際には別のデータ構造を使用する必要があります。たとえば、バイナリツリー/ヒープなどです。ソートされたリストを作成し、それを使用して新しいOrderedDict()インスタンスを初期化するこのアプローチは、データが完全に静的でない限り、ひどく非効率的です。

編集:したがって、データを並べ替える目的が、Pythondictオブジェクトに似た形式でデータを順番に印刷することだけである場合は、次のようなもので十分です。

def pprint_dict(d):
    strings = []
    for k in sorted(d.iterkeys()):
        strings.append("%d: '%s'" % (k, d[k]))
    return '{' + ', '.join(strings) + '}'

この関数は、キーのタイプと値のペアに対して柔軟性がないことに注意してください(つまり、キーは整数であり、対応する値は文字列である必要があります)。より柔軟性が必要な場合は、strings.append("%s: %s" % (repr(k), repr(d[k])))代わりに次のようなものを使用してください。

于 2012-06-18T19:30:18.087 に答える
3

Python 3.7では、次のことができます。

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(dict(sortDic))
{3:'a', 5:'c', 10: 'b'}

タプルのリストが必要な場合:

>>> myDic={10: 'b', 3:'a', 5:'c'}
>>> sortDic = sorted(myDic.items())
>>> print(sortDic)
[(3, 'a'), (5, 'c'), (10, 'b')]
于 2018-08-23T10:33:24.227 に答える
1

多分それほど良くはありませんが、私はこれを理解しました:

def order_dic(dic):
    ordered_dic={}
    key_ls=sorted(dic.keys())
    for key in key_ls:
        ordered_dic[key]=dic[key]
    return ordered_dic
于 2015-05-26T14:47:48.800 に答える
1

この問題に対する最新の解決策はありますか?私はそれを回避しました:

    order = sorted([ job['priority'] for job in self.joblist ])
    sorted_joblist = []
    while order:
        min_priority = min(order)
        for job in self.joblist:
            if job['priority'] == min_priority:
                sorted_joblist += [ job ]
                order.remove(min_priority)
    self.joblist = sorted_joblist

ジョブリストの形式は次のとおりです。joblist=[{'priority':3、'name':'foo'、...}、{'priority':1、'name':'bar'、...}]

  • 基本的に、辞書を並べ替えるすべての要素を含むリスト(順序)を作成します
  • 次に、このリストとdictを繰り返し、dictでアイテムを見つけたら、それを新しいdictに送信し、アイテムを「order」から削除します。

動作しているようですが、もっと良い解決策があると思います。

于 2016-11-26T07:27:34.040 に答える
1

これが役立つかどうかはわかりませんが、同様の問題が発生し、適切な関数を定義することで問題を解決することができました。

def sor_dic_key(diction):
    lista = []
    diction2 = {}
    for x in diction:
        lista.append([x, diction[x]])
    lista.sort(key=lambda x: x[0])
    for l in lista:
        diction2[l[0]] = l[1]
    return diction2

この関数は、同じキーと相対値を持つが、キーでソートされた別のディクショナリを返します。同様に、辞書をその値で並べ替えることができる関数を定義しました。ラムダ関数のx[1]代わりに使用する必要がありました。x[0]この2番目の関数はほとんど役に立たないと思いますが、誰にもわかりません。

于 2020-04-04T02:49:39.913 に答える
0

私はこの種のもののためにpythonnumpyが好きです!例えば:

r=readData()
nsorted = np.lexsort((r.calls, r.slow_requests, r.very_slow_requests, r.stalled_requests))

CSVデータをnumpyにインポートし、列の優先順位で並べ替える例があります。 https://github.com/unixunion/toolbox/blob/master/python/csv-numpy.py

ケガン

于 2012-06-18T19:52:22.720 に答える
0

受け入れられた答えは間違いなく機能しますが、どういうわけか重要な点を見逃しています。

OPは、それによってソートされた辞書を要求しています。keysこれは実際には不可能であり、何をしているのかではありませんOrderedDict

OrderedDictは、辞書の内容を挿入順に維持しています。最初のアイテムが挿入され、2番目のアイテムが挿入されます。

>>> d = OrderedDict()
>>> d['foo'] = 1
>>> d['bar'] = 2
>>> d
OrderedDict([('foo', 1), ('bar', 2)])

>>> d = OrderedDict()
>>> d['bar'] = 2
>>> d['foo'] = 1
>>> d
OrderedDict([('bar', 2), ('foo', 1)])

したがって、辞書をインプレースで並べ替えることはできませんが、挿入順序がキー順序と一致する新しい辞書を作成するだけです。これは、新しい辞書がbである受け入れられた回答で明示されています。

コンテナを介して辞書にアクセスし続ける場合、これは重要な場合があります。これは、後でアイテムを追加または削除して辞書を変更する場合にも重要です。アイテムはキー順に挿入されるのではなく、辞書の最後に挿入されます。

>>> d = OrderedDict({'foo': 5, 'bar': 8})
>>> d
OrderedDict([('foo', 5), ('bar', 8)])
>>> d['alpha'] = 2
>>> d
OrderedDict([('foo', 5), ('bar', 8), ('alpha', 2)])

さて、辞書をキーでソートすることはどういう意味ですか?これは、キーで要素にアクセスする場合には違いはありません。これは、アイテムを反復処理する場合にのみ問題になります。辞書自体のプロパティにするのはやり過ぎのようです。多くの場合、反復時にkeys()をソートするだけで十分です。

これは、次のことと同等であることを意味します。

>>> d = {'foo': 5, 'bar': 8}
>>> for k,v in d.iteritems(): print k, v

キーディクショナリでソートされた仮説または:

>>> d = {'foo': 5, 'bar': 8}
>>> for k, v in iter((k, d[k]) for k in sorted(d.keys())): print k, v

もちろん、イテレータをオーバーロードし、ソートされたキーリストを維持することによって、その動作をオブジェクトにラップすることは難しくありません。しかし、それはおそらくやり過ぎです。

于 2018-04-27T10:42:38.623 に答える
0

辞書は定義上順序付けられていません。キーで順序付けする主な理由は何でしょうか。sortメソッドによって作成されたタプルのリストは、必要に応じて使用できますが、タプルのリストを辞書に戻すと、ランダムな順序が返されます。

>>> myDic
{10: 'b', 3: 'a', 5: 'c'}
>>> sorted(myDic.items())
[(3, 'a'), (5, 'c'), (10, 'b')]
>>> print(dict(myDic.items()))
{10: 'b', 3: 'a', 5: 'c'}
于 2019-04-13T17:47:23.233 に答える
0

内包表記を使用して辞書を値でソートします。1行で、関数やラムダは必要ないと思います

a = {'b':'foo', 'c':'bar', 'e': 'baz'}
a = {f:a[f] for f in sorted(a, key=a.__getitem__)}
于 2019-12-14T17:26:22.710 に答える