使用自定义排序功能对词典进行排序 [英] Sort a dictionary with custom sorting function
问题描述
我有一些使用json.load(data_file)
{
"unused_account":{
"logins": 0,
"date_added": 150
},
"unused_account2":{
"logins": 0,
"date_added": 100
},
"power_user_2": {
"logins": 500,
"date_added": 400,
"date_used": 500
},
"power_user": {
"logins": 500,
"date_added": 300,
"date_used": 400
},
"regular_user": {
"logins": 20,
"date_added": 200,
"date_used": 300
}
}
我想按特定顺序对条目进行排序.我发现很多示例可以按键或单个值进行排序.但我想按以下规则对值进行排序:
I want to sort the entries in a specific order. I have found lots of examples to sort by key or one single value. But I would like to sort the values by these rules:
- groupby登录降序,但先登录0的用户
- 按日期添加的登录名对0个用户进行排序
- 按date_used排序至少登录1次的用户
理想情况下,我会这样编写自己的比较函数:
Ideally I would write my own compare function like this:
def compare(elem1, elem2):
"""Return >0 if elem2 is greater than elem1
<0 if elem2 is lesser than elem1
0 if they are equal"""
#rule 1 group by logins
if elem1['logins'] != elem2['logins']:
if elem1['logins'] == 0:
return -1
if elem2['logins'] == 0:
return 1
return elem2['logins'] - elem1['logins']
# rule 2 sort on date_added
if elem1['logins'] == 0 and elem2['logins'] == 0:
return elem2['date_added'] - elem1['date_added']
#rule 3 sort on date_used
if elem1['logins'] == elem2['logins'] and elem1['loigns'] > 0:
return elem2['date_used'] - elem1['date_used']
return 0 # default
我不知道在哪里以及如何插入我的排序功能.
I don't know where and how to plugin my sorting function.
推荐答案
我将假设您知道字典是无序的,并且要对值或键值对进行排序.以下示例对值进行排序.
I'm going to assume you know that dictionaries are unordered and that you want to sort either the values, or the key-value pairs. The following examples sort the values.
只要您在最后一个if
中修复了loigns
错字,您的比较功能就已经可以使用了:
Your comparison function already works, provided you fix the loigns
typo in the last if
:
>>> sorted(sample.itervalues(), cmp=compare))
[{'logins': 0, 'date_added': 150}, {'logins': 0, 'date_added': 100}, {'logins': 500, 'date_added': 400, 'date_used': 500}, {'logins': 500, 'date_added': 300, 'date_used': 400}, {'logins': 20, 'date_added': 200, 'date_used': 300}]
>>> pprint(_)
[{'date_added': 150, 'logins': 0},
{'date_added': 100, 'logins': 0},
{'date_added': 400, 'date_used': 500, 'logins': 500},
{'date_added': 300, 'date_used': 400, 'logins': 500},
{'date_added': 200, 'date_used': 300, 'logins': 20}]
但是,您也可以使用以下排序键:
However, you can use the following sort key too:
(not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added'])
这将创建一个(has_logins, num_logins, date)
元组,其中选择的日期取决于用户是否登录.
This creates a tuple of (has_logins, num_logins, date)
where the date picked is based on whether or not the user has logged in.
将其用作sorted()
函数的key
参数,并反转排序,如下所示:
Use it as the key
argument to the sorted()
function, and reverse the sort, like this:
>>> key = lambda d: (not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added'])
>>> pprint(sorted(sample.itervalues(), key=key, reverse=True))
[{'date_added': 150, 'logins': 0},
{'date_added': 100, 'logins': 0},
{'date_added': 400, 'date_used': 500, 'logins': 500},
{'date_added': 300, 'date_used': 400, 'logins': 500},
{'date_added': 200, 'date_used': 300, 'logins': 20}]
如果还需要键,请使用dict.iteritems()
并更新键功能以接受(k, d)
元组:
If you needed the keys as well, use dict.iteritems()
and update the key function to accept a (k, d)
tuple:
>>> key = lambda (k, d): (not d['logins'], d['logins'], d['date_used'] if d['logins'] else d['date_added'])
>>> pprint(sorted(sample.iteritems(), key=key, reverse=True))
[('unused_account', {'date_added': 150, 'logins': 0}),
('unused_account2', {'date_added': 100, 'logins': 0}),
('power_user_2', {'date_added': 400, 'date_used': 500, 'logins': 500}),
('power_user', {'date_added': 300, 'date_used': 400, 'logins': 500}),
('regular_user', {'date_added': 200, 'date_used': 300, 'logins': 20})]
这篇关于使用自定义排序功能对词典进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!