【Python】辞書の中身をソートして取り出すコード例

Python辞書(dict)のソート方法です。

早速ですが、『普通のやり方』と『高速な方法』のコードを紹介します。

 

『普通のやり方』です。

辞書の中身を『キー』でソートして取り出すコードです。

a = sorted(d.items(), key=lambda x: x[0])

 

辞書の中身をキーでソートして『上位を取り出す』コードです。

a = sorted(d.items(), key=lambda x: x[0])[0:3]

[0:3]は、スライスという機能です。

 

辞書の中身を『値』でソートするには、x[1] を指定します。

a = sorted(d.items(), key=lambda x: x[1])
a = sorted(d.items(), key=lambda x: x[1])[0:3]

 

『高速な方法』です。

アイテムゲッターを使うと、ラムダ式より高速にソートできます。

from operator import itemgetter
a = sorted(d.items(), key=itemgetter(0)) # キーでソートして取り出す
a = sorted(d.items(), key=itemgetter(0))[0:3] # 上位を取り出す

 

辞書の中身をソートしてから、上位を取り出したり、表示したりする場面は多かったです。

ですので、辞書とsorted()を組み合わせたコードはたくさん使ってきました。

特に、Python 3.6 以前は辞書に順番がなかったので、キーをソートしてからfor文にかける場面が良くありました。

以下、辞書をソートするコードの全体と、ラムダ式 vs アイテムゲッターの速さ比較です。

スポンサーリンク

辞書の中身をソートして取り出すコード例

Pythonの辞書順をソートして取り出すコード例です。

辞書の中身をソートして取り出すには、辞書のアイテム d.items() を sorted() に渡します。

ところで、もし、辞書の順番に重要な意味があって、順序を保持した辞書を作りたいときは、オーダードディクトOrderedDict() をインポートして使うのがおすすめです。

sorted()の戻り値をOrderedDict()に渡せば、ソート結果を維持した新しい辞書が得られます。

普通の辞書とオーダードディクトの違いを調べた記事もあります。

Python 3.7 以降なら、普通のdict()にsorted()を渡しても順序が維持できます。

ラムダ式で辞書をソートする

ラムダ式(lambda)でソートするのが一番簡単です。

辞書(dict)、sorted()、ラムダ式の公式マニュアルの場所です。

以下、コード例です。

"""辞書をキーでソートしてから取り出す方法"""

# 辞書のアイテムリストを作成
d_items = [(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

# 辞書を生成
d = dict(d_items)

print('辞書のアイテムを表示')
print(list(d.items()))

print('辞書を『キー』でソートしてから取り出す(昇順)')
z0 = sorted(d.items(), key=lambda x: x[0])
print(z0)

print('辞書を『値』でソートしてから取り出す(昇順)')
z1 = sorted(d.items(), key=lambda x: x[1])
print(z1)

実行結果です。

バラバラに並んだアイテムから、『キーの数字順』や『値のひらがな順』で取り出せました。

辞書のアイテムを表示
[(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

辞書を『キー』でソートしてから取り出す(昇順)
[(1, 'お'), (2, 'え'), (3, 'う'), (4, 'い'), (5, 'あ')]

辞書を『値』でソートしてから取り出す(昇順)
[(5, 'あ'), (4, 'い'), (3, 'う'), (2, 'え'), (1, 'お')]
スポンサーリンク

辞書をソートして上位を取り出す

辞書のソート結果の『上位だけ取得』する時のコードです。

上位の取り出しは、Pythonのスライスで取り出します。

スライス表記の公式マニュアルの場所です。

式 (expression) スライス表記 (slicing)

sorted()の後ろにスライス[0:3]をくっつけると、上位のリストが返ります。

"""辞書をソートして上位を取り出す方法"""

# 辞書のアイテムリストを作成
d_items = [(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

# 辞書を生成
d = dict(d_items)

print('辞書のアイテムを表示')
print(list(d.items()))

print('辞書を『キー』でソートして、スライス[0:3]で上位を取り出す。')
z1 = sorted(d.items(), key=lambda x: x[0])[0:3]
print(z1)

print('辞書を『値』でソートして、スライス[0:3]で上位を取り出す。')
z2 = sorted(d.items(), key=lambda x: x[1])[0:3]
print(z2)

実行結果です。

辞書のソート結果から『上位の部分』を取り出せました。

辞書のアイテムを表示
[(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

辞書を『キー』でソートして、スライス[0:3]で上位を取り出す。
[(1, 'お'), (2, 'え'), (3, 'う')]

辞書を『値』でソートして、スライス[0:3]で上位を取り出す。
[(5, 'あ'), (4, 'い'), (3, 'う')]

アイテムゲッターで辞書をソートする

アイテムゲッター(itemgetter)をインポートして使うと、ラムダ式よりも高速にソートできます。

itemgetter()はCSVを読み込むときによく使っています。EDINETコードや証券コードの一覧から、必要な列だけ選んで辞書やリストを作るときに高速化できました。

アイテムゲッターの公式マニュアルの場所です。

operator — 関数形式の標準演算子 operator.itemgetter(item)

公式マニュアルには、速さに関しての言及がありました。

operator モジュールは属性とアイテムの汎用的な検索のための道具も定義しています。 map(), sorted(), itertools.groupby(), や関数を引数に取るその他の関数に対して高速にフィールドを抽出する際に引数として使うと便利です。

operator — 関数形式の標準演算子

以下、コード例です。

"""辞書をキーでソートしてから取り出す方法(高速)"""
from operator import itemgetter

# 辞書のアイテムリストを作成
d_items = [(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

# 辞書を生成
d = dict(d_items)

print('辞書のアイテムを表示')
print(list(d.items()))

print('辞書を『キー』でソートしてから取り出す(昇順)')
z0 = sorted(d.items(), key=itemgetter(0))
print(z0)

print('辞書を『値』でソートしてから取り出す(昇順)')
z1 = sorted(d.items(), key=itemgetter(1))
print(z1)

実行結果です。

もちろん、結果はラムダ式の場合と同じになりました。

辞書のアイテムを表示
[(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

辞書を『キー』でソートしてから取り出す(昇順)
[(1, 'お'), (2, 'え'), (3, 'う'), (4, 'い'), (5, 'あ')]

辞書を『値』でソートしてから取り出す(昇順)
[(5, 'あ'), (4, 'い'), (3, 'う'), (2, 'え'), (1, 'お')]

次は、ラムダ式とアイテムゲッターのソート時間を計ります。

スポンサーリンク

ラムダ式 vs アイテムゲッターの速さ比較

タイムイット(timeit)で辞書のソート時間を計りました。

結果は、アイテムゲッターを使ったほうが、少し速かったです。

なので、巨大な辞書をソートするなら、アイテムゲッターをインポートして使うメリットが出てきます。

"""辞書のソート速度を比較"""
from operator import itemgetter
import timeit

# 辞書のアイテムリストを作成
d_items = [(5, 'あ'), (2, 'え'), (4, 'い'), (1, 'お'), (3, 'う')]

# 辞書を生成
d = dict(d_items)

# 変数名の辞書を取得
g = globals()

# 繰り返し回数 100万回
NUMBER = 1000000

# 辞書のアイテムをキーでソートして取り出す(ラムダ式)
ta = timeit.timeit('sorted(d.items(), key=lambda x: x[0])', globals=g, number=NUMBER)
print('%f seconds  sorted(d.items(), key=lambda x: x[0])' % ta)

# 辞書のアイテムをキーでソートして取り出す(アイテムゲッター)
tb = timeit.timeit('sorted(d.items(), key=itemgetter(0))', globals=g, number=NUMBER)
print('%f seconds  sorted(d.items(), key=itemgetter(0))' % tb)

アイテムゲッターのほうが速かった

100万回の実行に要した時間は、アイテムゲッターのほうが短かった(速かった)です。

1.377055 seconds  sorted(d.items(), key=lambda x: x[0])
1.239298 seconds  sorted(d.items(), key=itemgetter(0))
タイトルとURLをコピーしました