【问题标题】:Stable Sort for Dictionary-Values in PythonPython中字典值的稳定排序
【发布时间】:2016-02-17 17:18:38
【问题描述】:

我是 Python 新手,目前正在努力解决问题以提高我的编码技能。我正在研究一个需要stable sort python 中的字典的问题。请在下面找到详细信息:

输入:

1 2
16 3
11 2
20 3
3 5
26 4
7 1
22 4

以上输入,我已经添加成两个lists k and v

k = ['1', '16', '11', '20', '3', '26', '7', '22']
v = ['2', '3', '2', '3', '5', '4', '1', '4']

我已将这两个列表添加到字典中,以将其作为键值对。我使用了OrderDict,因为我希望元素的顺序与输入中的顺序相同。

from collections import OrderedDict
d = OrderedDict(zip(k, v))

现在,我需要按照与值相反的顺序对字典 d 进行排序。 (实际上我必须做一个稳定的排序,因为 python 中的sorted 是一个稳定的排序,所以我使用了它。来源:Here)为此:

s = sorted(d, key = itemgetter(1), reverse=True)

预期输出:

 3 5
26 4
22 4
16 3
20 3
1 2
11 2
7 1

但是在我实现了上面的sorted 函数之后,我无法得到预期的输出。我得到IndexError: string index out of range

谁能告诉我我哪里做错了。我的方法是错误的还是流程是错误的?您能否告诉我为什么我无法按预期获得输出。提前致谢。任何帮助将不胜感激。

【问题讨论】:

    标签: python sorting dictionary


    【解决方案1】:

    您忘记使用.items() (Python3) 或.iteritems() (Python2) 访问字典中的项目。

    此外,您需要导入operator 模块才能使用itemgetter()

    所以代码看起来像:

    import operator
    from collections import OrderedDict
    
    k = ['1', '16', '11', '20', '3', '26', '7', '22']
    v = ['2', '3', '2', '3', '5', '4', '1', '4']
    
    d = OrderedDict(zip(k, v))
    
    out = sorted(d.items(), key=operator.itemgetter(1), reverse=True)
    

    列表out 是这样的:

    [('3', '5'), ('26', '4'), ('22', '4'), ('16', '3'), ('20', '3'), ('1', '2'), ('11', '2'), ('7', '1')]
    

    为了打印,您可以使用以下命令访问列表的每个元组:

    for i,k in out:
        print(i,k) 
    

    提供所需的输出:

    3 5
    26 4
    22 4
    16 3
    20 3
    1 2
    11 2
    7 1
    

    我已经编写了上面给出的代码示例,可以在ideone.com 找到。

    【讨论】:

    • 谢谢,我在验证时确实尝试过,但我得到了string index out of range 错误:(。你给出的输出不是预期的输出。我给了导入运算符
    • 输出列表out 是您想要的顺序。如果你想打印它,你只需要访问列表中的每个元组。请看我更新的答案。
    • 谢谢。有效。很抱歉没有早点得到你。你能告诉我如果我不使用d.items()而只给d会发生什么吗?它不会迭代元素吗?
    • 看看这个example和文档herehere
    【解决方案2】:

    这是一种方法:

    >>> sorted_kv = sorted(d.items(), key=lambda (k,v):int(v), reverse=True)
    >>> OrderedDict(sorted_kv)
    OrderedDict([('3', '5'), ('26', '4'), ('22', '4'), ('16', '3'), ...
    

    这会从字典中获取键/值对,对它们进行排序,并创建一个具有所需顺序的新有序字典。

    sorted()key= 参数指定将根据第二项的数值对这些对进行排序。

    我需要调用int() 的原因是您的字典将键和值都保存为字符串。按原样对它们进行排序会起作用,但会生成 lexicographic ordering 而不是数字。

    【讨论】:

    • 感谢您的详细解释。我有几个疑问 - 1. 为什么字典将键和值保留为字符串,即使所有值都是整数。 2. 用d 代替d.items 有什么不同吗?目的是什么。对不起,如果它听起来很傻,但我只是想更好地理解。
    • @Dev 1) Python 是强类型的。这意味着它不会在类型之间进行静默转换;你必须通过强制转换来强制它。有些地方放宽了一些(例如,不同类型之间的数学运算)。即使字符串只包含数字字符,它们仍然是字符串并且永远不会被视为任何不同的东西,除非你明确地将它们转换为其他东西。 2) 仅迭代 d 只会给你密钥。 d.items() 返回 (key, value) 的元组。基本上,它可以为您节省更多的字典查找时间。
    【解决方案3】:

    这是另一种方法:

    from collections import OrderedDict
    
    k = ['1', '16', '11', '20', '3', '26', '7', '22']
    v = ['2', '3', '2', '3', '5', '4', '1', '4']
    
    d = OrderedDict(zip([int(x) for x in k], [int(y) for y in v]))  # convert from string to int
    sorted_items = sorted(d.items())
    sorted_items.reverse()
    s = OrderedDict(sorted_items)  # new sorted ordered dict
    

    【讨论】:

      【解决方案4】:

      这是我对这项任务的一些想法:

      k = ['1', '16', '11', '20', '3', '26', '7', '22']
      v = ['2', '3', '2', '3', '5', '4', '1', '4']
      
      # create a dictionary
      d = dict([(k[ind], v[ind]) for ind in range(0, len(k))])
      
      for order in sorted(d, key=d.__getitem__, reverse=True):
          print ("{}: {}".format(order, d[order]))
      

      输出:

      3: 5
      26: 4
      22: 4
      16: 3
      20: 3
      11: 2
      1: 2
      7: 1
      

      但我注意到,在您的预期输出中,“1”在“11”之前。有什么原因吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-28
        • 1970-01-01
        • 2013-05-01
        • 2022-11-12
        • 2021-05-01
        • 1970-01-01
        • 2017-01-23
        • 2017-12-17
        相关资源
        最近更新 更多