简体   繁体   English

Python 2.5字典2键排序

[英]Python 2.5 dictionary 2 key sort

I have a dictionary of 200,000 items (the keys are strings and the values are integers). 我有一个200,000项的字典(键是字符串,值是整数)。

What is the best/most pythonic way to print the items sorted by descending value then ascending key (ie a 2 key sort)? 什么是打印项目的最佳/最pythonic方式,按降序值排序,然后按升序键(即2键排序)?

 a={ 'keyC':1, 'keyB':2, 'keyA':1 }
b = a.items()
b.sort( key=lambda a:a[0])
b.sort( key=lambda a:a[1], reverse=True )
print b
>>>[('keyB', 2), ('keyA', 1), ('keyC', 1)]

You can't sort dictionaries. 你不能排序词典。 You have to sort the list of items. 您必须对项目列表进行排序。

Previous versions were wrong. 以前的版本错了。 When you have a numeric value, it's easy to sort in reverse order. 如果有数值,则可以按相反顺序排序。 These will do that. 这些就是这样做的。 But this isn't general. 但这不是一般的。 This only works because the value is numeric. 这只能起作用,因为值是数字。

a = { 'key':1, 'another':2, 'key2':1 }

b= a.items()
b.sort( key=lambda a:(-a[1],a[0]) )
print b

Here's an alternative, using an explicit function instead of a lambda and the cmp instead of the key option. 这是一个替代方案,使用显式函数而不是lambda和cmp而不是key选项。

def valueKeyCmp( a, b ):
    return cmp( (-a[1], a[0]), (-b[1], b[0] ) )

b.sort( cmp= valueKeyCmp )
print b

The more general solution is actually two separate sorts 更通用的解决方案实际上是两种不同的排序

b.sort( key=lambda a:a[1], reverse=True )
b.sort( key=lambda a:a[0] )
print b
data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), key=lambda x: (-1*x[1], x[0])):
    print key, value

The most pythonic way to do it would be to know a little more about the actual data -- specifically, the maximum value you can have -- and then do it like this: 最诡计多端的方法是更多地了解实际数据 - 特别是你可以拥有的最大值 - 然后像这样做:

def sortkey((k, v)): 
    return (maxval - v, k)

items = thedict.items()
items.sort(key=sortkey)

but unless you already know the maximum value, searching for the maximum value means looping through the dict an extra time (with max(thedict.itervalues()) ), which may be expensive. 但除非你已经知道最大值,否则搜索最大值意味着在dict中循环一个额外的时间(使用max(thedict.itervalues()) ),这可能很昂贵。 Alternatively, a keyfunc version of S.Lott's solution: 或者,S.Lott解决方案的keyfunc版本:

def sortkey((k, v)): 
    return (-v, k)

items = thedict.items()
items.sort(key=sortkey)

An alternative that doesn't care about the types would be a comparison function: 不关心类型的替代方案是比较函数:

def sortcmp((ak, av), (bk, bv)):
    # compare values 'in reverse'  
    r = cmp(bv, av)
    if not r:
        # and then keys normally
        r = cmp(ak, bk)
    return r

items = thedict.items()
items.sort(cmp=sortcmp) 

and this solution actually works for any type of key and value that you want to mix ascending and descending sorting with in the same key. 此解决方案实际上适用于您希望在同一个键中混合升序和降序排序的任何类型的键和值。 If you value brevity you can write sortcmp as: 如果您重视简洁,可以将sortcmp写为:

def sortcmp((ak, av), (bk, bv)):
    return cmp((bk, av), (ak, bv))

You can use something like this: 你可以使用这样的东西:

dic = {'aaa':1, 'aab':3, 'aaf':3, 'aac':2, 'aad':2, 'aae':4}

def sort_compare(a, b):
    c = cmp(dic[b], dic[a])
    if c != 0:
        return c
    return cmp(a, b)

for k in sorted(dic.keys(), cmp=sort_compare):
    print k, dic[k]

Don't know how pythonic it is however :) 不知道pythonic是多少:)

Building on Thomas Wouters and Ricardo Reyes solutions: 以Thomas Wouters和Ricardo Reyes解决方案为基础:

def combine(*cmps):
    """Sequence comparisons."""
    def comparator(a, b):
        for cmp in cmps:
            result = cmp(a, b):
            if result:
                return result
        return 0
    return comparator

def reverse(cmp):
    """Invert a comparison."""
    def comparator(a, b):
        return cmp(b, a)
    return comparator

def compare_nth(cmp, n):
    """Compare the n'th item from two sequences."""
    def comparator(a, b):
        return cmp(a[n], b[n])
    return comparator

rev_val_key_cmp = combine(
        # compare values, decreasing
        reverse(compare_nth(1, cmp)),

        # compare keys, increasing
        compare_nth(0, cmp)
    )

data = { 'keyC':1, 'keyB':2, 'keyA':1 }

for key, value in sorted(data.items(), cmp=rev_val_key_cmp):
    print key, value
>>> keys = sorted(a, key=lambda k: (-a[k], k))

or 要么

>>> keys = sorted(a)
>>> keys.sort(key=a.get, reverse=True)

then 然后

print [(key, a[key]) for key in keys]
[('keyB', 2), ('keyA', 1), ('keyC', 1)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM