Python嵌套字典键顺序不符合预期,如何让sign-in排在首位?
问题
我有一个包含三项内容的日志列表:userid、time、sign-in或sign-out,日志数据如下:
logs = ["12 150 sign-out","30 90 sign-in","12 10 sign-in","30 120 sign-out"]
我尝试创建一个嵌套字典结构,编写的代码如下:
outlist = {} for log in logs: buff = log.split() if buff[0] not in outlist.keys(): outlist[buff[0]] = {} if buff[2] == 'sign-in': outlist[buff[0]].update({'sign-in':buff[1]}) elif buff[2] == 'sign-out': outlist[buff[0]]['sign-out']=buff[1]
生成的outlist结果如下:
{'12': {'sign-out': '150', 'sign-in': '10'}, '30': {'sign-in': '90', 'sign-out': '120'}}
我期望得到如下结果,让sign-in排在前面:
{'12': {'sign-in': '10','sign-out': '150'}, '30': {'sign-in': '90', 'sign-out': '120'}}
我尝试使用update方法将sign-in插入到开头,但没有效果,请问问题出在哪里?
解答
问题根源
Python 3.7之前的普通字典是无序的,键的顺序由插入、删除操作决定;即便在Python 3.7+中字典会保留插入顺序,但你的代码里userid=12的日志先插入了sign-out,后插入sign-in,所以最终sign-out排在前面。而update()方法仅会更新键值对,无法改变已有键的顺序,因此用它调整顺序无效。
解决方案
有两种实用的处理方式:
预设键的顺序
在初始化用户字典时,直接先创建sign-in键,后续再填充对应值,这样不管日志的顺序如何,键的顺序都会固定:outlist = {} for log in logs: buff = log.split() user_id, time, action = buff # 初始化时先设置好固定顺序的键 if user_id not in outlist: outlist[user_id] = {'sign-in': None, 'sign-out': None} # 直接给对应动作的键赋值 outlist[user_id][action] = time使用OrderedDict(兼容旧版本Python)
如果需要兼容Python 3.7以前的版本,可以用collections.OrderedDict手动控制键的顺序:from collections import OrderedDict outlist = {} for log in logs: buff = log.split() user_id, time, action = buff if user_id not in outlist: # 初始化OrderedDict时先添加sign-in outlist[user_id] = OrderedDict([('sign-in', None)]) # 赋值对应动作的时间 outlist[user_id][action] = time # 确保sign-out始终在sign-in之后 if 'sign-out' in outlist[user_id]: outlist[user_id].move_to_end('sign-out')
内容的提问来源于stack exchange,提问作者Zenvega
相关产品推荐
相关产品推荐

