8

我想使用各种比较器功能对字典中的项目进行排序。请参阅下面的示例代码。这是使用 cmpRatio 函数和 sorted() 不起作用的最后一部分。我不确定我做错了什么。提前感谢您的任何想法!

mydict = { 'a1': (1,6),
          'a2': (10,2),
          'a3': (5,3),
          'a4': (1,2),
          'a5': (3,9),
          'a6': (9,7) }

# sort by first element of the value tuple: WORKS
print sorted(mydict.iteritems(), key=lambda (k,v): v[0])

# sort by second element of the value tuple: WORKS
print sorted(mydict.iteritems(), key=lambda (k,v): v[1])

# THIS is what I can't get working:
def cmpRatio(x,y):
   sx = float(x[0])/x[1]
   sy = float(y[0])/y[1]
   return sx < sy

# sort by sum of the elements in the value tuple: DOES NOT WORK
print sorted(mydict.iteritems(), key=lambda (k,v): v, cmp=cmpRatio)
4

3 回答 3

6

尽可能避免cmp使用函数,因为它们很慢。每次比较都必须重新评估它们。使用 akey使得密钥只需要计算一次。

print sorted(mydict.iteritems(), key=lambda (k,v): float(v[0])/v[1])

此外,您说您想按价值项的总和进行排序,但您正在按差异排序。总和看起来像:

print sorted(mydict.iteritems(), key=lambda (k,v): sum(v))

正如其他答案中所提到的,出于真正想要定义cmp函数的目的,您没有返回正确的值(必须是-1、0 或 1)。

return cmp(sx,sy)

但是,如果您只是使用 lambda 来获取值,则可以将其替换为itemgetter应该比 python 端函数更快的值:

from operator import itemgetter

print sorted(mydict.iteritems(), key=itemgetter(1), cmp=cmpRatio)

如果您尝试存储排序操作,最好存储关键函数:

key_ops = {
    'sum': lambda (k,v): sum(v),
    'ratio': lambda (k,v): float(v[0])/v[1]),
}

def print_op(aDict, opName):
    print sorted(aDict.iteritems(), key=key_ops[opName])

... # some place later in code
print_op(mydict, 'sum')
于 2012-11-21T20:01:11.190 回答
4

当第一个参数是(小于/等于/大于)第二个值(与std::sort(...)C++ 中给出的比较器不同)时,您的比较函数应该返回一个(负/零/正)值。

即代替

return sx < sy

return cmp(sx,sy)
于 2012-11-21T20:01:48.740 回答
2

如果您想按值元组的总和进行排序(根据您的评论),您可以使用:

print sorted(mydict.iteritems(), key=lambda v: sum(v[1]))

如果您想按比率排序(根据您的代码):

print sorted(mydict.iteritems(), key=lambda v: float(v[1][0])/v[1][1])
于 2012-11-21T20:00:33.843 回答