【问题标题】:how does sorted(dict, dict.get) work for duplicate valuessorted(dict, dict.get) 如何处理重复值
【发布时间】:2012-09-15 21:58:00
【问题描述】:

假设我在 python 中有一个字典,我按值对键进行排序,如下所示

my_dict = {'a':5, 'b':4, 'c':6, 'd':3, 'e':2}
sorted_list = sorted(my_dict, key=my_dict.get)
sorted_list
['e', 'd', 'b', 'a', 'c']

这很好用,但如果我的字典中有冲突(关于值)

my_dict = {'a':5, 'b':4, 'c':5, 'd':3, 'e':2, 'f':4, 'g':3}
sorted_list = sorted(my_dict, key=my_dict.get)
sorted_list
['e', 'd', 'g', 'b', 'f', 'a', 'c']

在我看来,在重复的情况下,列表按其在字典中的顺序(数字顺序或插入顺序,而不是排序顺序)排序。我可以假设它适用于所有情况吗?

EDIT1:我的键将是整数,如果值发生冲突,我希望结果键按它们的值排序(最高优先)

EDIT2:添加以下参数有助于我的问题。但是,在我的情况下,我希望值按升序排序,但键按降序排序。以下将导致两者都下降 键=lambda x: (x[1],x[0])

【问题讨论】:

  • 升序降序将第二项设为负数:sorted(my_dict, key=lambda k: (my_dict[k],-k)。请注意,这只会为您提供排序的键。如果您需要排序的键值对,请执行以下操作:sorted(my_dict.iteritems(), key=lambda item: (item[0], -item[1]))

标签: python sorting dictionary


【解决方案1】:

Python 的排序算法 (TimSort) 是一种稳定的排序,因此任何具有相同排序“值”的项目都将按照排序前的顺序保持。

在对字典键进行排序时,这意味着它们的顺序与dict.keys() 返回的顺序相同,或者在迭代字典时。请注意,这种排序是任意的,并且在字典的更改中不稳定。

否则是的,您可以假设所有情况都是如此。

正如Steven Rumbalski所指出的,您可以将key与排序一起使用以稳定同值排序顺序:

sorted_list = sorted(my_dict, key=lambda k: (my_dict[k], k))

【讨论】:

  • 这取决于他所说的“它在字典中的顺序”是什么意思。如果他的意思是dict.keys() 返回的订单,那么,是的,这是真的。但是,如果他的意思是出现在 dict 文字中的顺序,那么假设是不正确的。他的第二个例子对这两种解释都是开放的。
  • @StevenRumbalski:我稍微限定了我的“是”,我意识到 OP 可能错误地认为他的 dict 文字定义可能指定了一个顺序。
  • 我把问题说得更清楚了。我的意思是插入顺序或数字顺序(不是排序顺序)
  • @HimanshuJindal:如果您关心插入顺序,请使用 OrderedDict,它将按照插入顺序返回键。
  • 要按key的值排序,你的key函数需要返回值:key=lambda k:(my_dict[k], k)
【解决方案2】:

这不是真的。当值相同时,字典按键排序。这是修改后的示例。

my_dict = {'a':5, 'b':4, 'c':5, 'z':3, 'e':2, 'f':4, 'g':3}
sorted_list = sorted(my_dict, key=my_dict.get)
print sorted_list

【讨论】:

  • 这个反例在不同的 python 中可能不会产生相同的结果。另外,“按键排序”是指 my_dict.keys() 返回的 order 还是键值?
  • 这个有参考吗?因为我将在大量数据上运行它,我想确定这是否正确
  • sorted_list 在我的 Python 2.7.3 中是 ['e', 'g', 'z', 'b', 'f', 'a', 'c'],在我的 Jython 2.5.1+ 中是 ['e', 'g', 'z', 'b', 'f', 'c', 'a']。正如@StevenRumbalski 所说,这因 Python 实现而异,因 Python 实现而异,并且由于没有任何保证,因此可能会随着月相的变化而变化。
  • 那么最好是明确的 - 就像为stackoverflow.com/questions/7742752/…提供的解决方案一样
【解决方案3】:

这可能与您正在寻找的内容接近,使用 pypy.陷阱的东西在http://stromberg.dnsalias.org/~strombrg/treap/ 请注意,我已经翻转了键和值;在某些问题中是有益的,而在您的问题中可能会也可能不会。

#!/usr/local/pypy-1.8/bin/pypy

import py_treap

class Thing:
    def __init__(self, number):
        self.number = number

    def __cmp__(self, other):
        return -cmp(self.number, other.number)

    def __str__(self):
        return str(self.number)

def main():
    list_ = [ ('a', 5), ('b', 4), ('c', 6), ('d', 3), ('e', 2), ('f', 4), ('g', 4), ('h', 3) ]
    t = py_treap.treap()
    for string, integer in list_:
        thing = Thing(integer)
        if not thing in t:
            print '%s not in t' % thing
            t[thing] = [ string ]
        else:
            print '%s in t' % thing
            t[thing].append(string)

    for sublist in t.values():
        sublist.sort()

    for key, value in t.items():
        print key, value

main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 2017-11-07
    • 2012-06-17
    • 2020-07-19
    相关资源
    最近更新 更多