hogeとはワイルドカードのようなものです。日々起こった、さまざまなこと −すなわちワイルドカード− を取り上げて日記を書く、という意味で名付けたのかというとそうでもありません。適当に決めたらこんな理由が浮かんできました。
11/28/2013 うむ [長年日記]
tDiary 4053日目
■ [Py][メモ] 辞書のリストを色んな型でソート
タイトルだけではなんのこっちゃという感じかもだけど,要はこういうこと.これを key1, 2, 3 で複合的にそれっぽくソートしてみる.
iterable = (
{
'key1': '1',
'key2': '192.168.0.2',
'key3': 'あいう',
'val': 'hoge',
},
{
'key1': '0x0e',
'key2': '192.168.0.22',
'key3': 'えおか',
'val': 'hage',
},
{
'key1': '0x0e',
'key2': '192.168.0.3',
'key3': 'きくけ',
'val': 'hige',
},
{
'key1': '1',
'key2': '192.168.1.20',
'key3': 'こさし',
'val': 'huge',
},
{
'key1': '1',
'key2': '192.168.0.2',
'key3': 'すせそ',
'val': 'hege',
},
)
ソート HOWTO を読むと operator.itemgetter が何やらそれっぽいのだけれど,残念ながら (当然ながら) 文字列に対しては文字列的にしかソートできない ("1" -> "11" -> "2" になる).
itemgetter の内部処理を外部的にいじくる良い方法は思いつかないので,こんな関数を作ってみる.
def itemgetter2(*items):
def g(obj):
return tuple(item[1](obj[item[0]], *item[2:]) for item in items)
return g
で,こんな風に呼んでみる.
import socket
import locale
result = sorted(iterable, key=itemgetter2(('key1', int, 16),
('key2', socket.inet_aton),
('key3', locale.strxfrm)))
結果は下記の通り.めでたしめでたし.
[{'key1': '1',
'key2': '192.168.0.2',
'key3': 'あいう',
'val': 'hoge'},
{'key1': '1',
'key2': '192.168.0.2',
'key3': 'すせそ',
'val': 'hege'},
{'key1': '1',
'key2': '192.168.1.20',
'key3': 'こさし',
'val': 'huge'},
{'key1': '0x0e',
'key2': '192.168.0.3',
'key3': 'きくけ',
'val': 'hige'},
{'key1': '0x0e',
'key2': '192.168.0.22',
'key3': 'えおか',
'val': 'hage'}]
[ツッコミを入れる]