如何显式基于date和name多键对Python字典进行排序?
问题描述
给定如下Python字典数据:
results = { "a":{ "date":"20140206", "bytes":"154", "name":"cos" }, "b":{ "date":"20140207", "bytes":"300", "name":"cos" }, "c":{ "date":"20140206", "bytes":"279", "name":"phil" }, "d":{ "date":"20140207", "bytes":"241", "name":"phil" } }
需求是先按date属性排序,再按name属性排序。目前使用以下代码能得到预期的排序结果:
import collections results = collections.OrderedDict(sorted(results.items()))
预期输出:
results = { "a":{ "date":"20140206", "bytes":"154", "name":"cos" }, "c":{ "date":"20140206", "bytes":"279", "name":"phil" }, "b":{ "date":"20140207", "bytes":"300", "name":"cos" }, "d":{ "date":"20140207", "bytes":"241", "name":"phil" } }
但不清楚这段代码为什么能实现先按date再按name排序,同时想知道有没有显式指定先按date、再按name排序的其他实现方式。
解答
一、当前代码生效的原因
sorted(results.items())默认会对字典的键值对按键进行字符串排序。你的字典键"a"、"b"、"c"、"d"的排序顺序,刚好和date+name的排序结果完全重合:
"a"对应date=20140206+name=cos,是第一顺位"c"对应date=20140206+name=phil,是第二顺位"b"对应date=20140207+name=cos,是第三顺位"d"对应date=20140207+name=phil,是第四顺位
这完全是巧合——如果键的命名规则改变(比如把"c"改成"e"),这段代码就会失效,因为它本质是按字典键排序,而非值里的date和name。
二、显式指定排序规则的实现方式
要真正按照date优先、name次之的规则排序,需给sorted()传入key参数,明确指定排序依据:
方法1:用lambda表达式定义排序键
import collections # 先按date升序,再按name升序排序 sorted_items = sorted(results.items(), key=lambda x: (x[1]['date'], x[1]['name'])) results_sorted = collections.OrderedDict(sorted_items)
这里lambda x: (x[1]['date'], x[1]['name'])表示:对每个键值对x,先取对应值的date作为第一排序维度,再取name作为第二维度。
方法2:用operator.itemgetter(效率更高)
数据量较大时,operator.itemgetter比lambda表达式的执行效率更高:
import collections from operator import itemgetter # 直接指定取值路径 sorted_items = sorted(results.items(), key=lambda x: itemgetter('date', 'name')(x[1])) results_sorted = collections.OrderedDict(sorted_items)
方法3:Python 3.7+ 直接用普通字典
Python 3.7及以上版本中,普通字典已经默认保留插入顺序,无需再用OrderedDict:
from operator import itemgetter sorted_items = sorted(results.items(), key=lambda x: (x[1]['date'], x[1]['name'])) results_sorted = dict(sorted_items)
这些方法都明确绑定了排序规则,不会依赖键的命名巧合,适用性更强。
内容的提问来源于stack exchange,提问作者fiona_neu
相关产品推荐
相关产品推荐

