【问题标题】:Reordering Dictionary based on specific order根据特定顺序重新排序字典
【发布时间】:2012-12-11 02:52:31
【问题描述】:

我有以下键值格式的字典:

PairDict= {(19, 6): 13, (2, 29): 10, (38, 8): 20, (38, 5): 5} 

键是一个有两个元素的元组,值表示循环的次数。

我需要根据元组第一个元素的给定排序顺序将字典重新排序为列表,例如

SortOrder= [(38, 25), (19, 13), (2, 10)]

其中,上面SortOrder中元组的第一个元素表示PairDict中元组键的第一个元素。 SortOrder 中元组的第二个元素表示 PairDict 中第一个元素的循环数之和

如果 PairDict 有多个具有相同第一个元素的元组,则无论如何它的排序顺序都可以,例如 38需要先排序,PictDict中有两个以38开头的元组,即(38, 8)(38, 5)。它的顺序可以是[(38, 8): 20, (38, 5): 5][(38, 5): 5, (38, 8): 20]

基于 SortOrder 的排序 PairDict 的预期输出可以是,

SortedPairDict= [((38, 8), 20), ((38, 5), 5), ((19, 6), 13), ((2, 29), 10)], 

SortedPairDict= [((38, 5), 5), ((38, 8), 20), ((19, 6), 13), ((2, 29), 10)],

试图搜索,我能得到的最接近的例子是,

参考:reordering list of dicts arbitrarily in python

但是用那个例子来实现我的代码有问题,因为我的键是一个元组。

如果有任何我可以阅读的示例,请您指出我,或者指导我如何处理这个问题的最佳方法。

感谢您的帮助。圣诞快乐:-)

谢谢。

更新:timeit 分析 Amber 和 Ashwini 的解决方案

PairDict= {(19, 8): 13, (2, 29): 10, (38, 8): 20, (2, 18): 10, (43, 8): 20, (5, 13): 15, (6, 21): 9, (7, 25): 11, (8, 19): 15, (44, 4): 20, (0, 10): 9, (0, 36): 9, (21, 6): 19, (30, 4): 17, (24, 0): 11, (3, 14): 21, (6, 12): 9, (7, 20): 11, (20, 7): 10, (5, 23): 15, (11, 5): 15, (37, 6): 13, (34, 8): 20, (18, 2): 10, (0, 24): 9, (12, 6): 13, (8, 38): 15, (39, 5): 18, (42, 5): 17, (26, 7): 22, (10, 0): 9, (31, 0): 14, (3, 27): 21, (6, 37): 9, (36, 0): 17, (0, 33): 9, (41, 0): 18, (5, 39): 15, (5, 42): 15, (6, 40): 9, (5, 11): 15, (9, 3): 21, (25, 7): 13, (7, 28): 11, (3, 9): 21, (29, 2): 4, (32, 4): 22, (0, 41): 9, (40, 6): 10, (28, 7): 20, (6, 15): 9, (17, 4): 23, (23, 5): 18, (16, 5): 23, (8, 34): 15, (5, 16): 15, (8, 22): 15, (8, 43): 15, (4, 17): 19, (13, 5): 23, (4, 30): 19, (7, 26): 11, (15, 6): 13, (4, 44): 19, (22, 8): 18, (0, 31): 9, (35, 5): 23, (14, 3): 20, (33, 0): 12, (5, 35): 15, (27, 3): 16, (4, 32): 19}

SortOrder= [(5, 105), (4, 76), (8, 75), (3, 63), (0, 54), (6, 45), (7, 44), (13, 23), (16, 23), (17, 23), (35, 23), (26, 22), (32, 22), (9, 21), (2, 20), (14, 20), (28, 20), (34, 20), (38, 20), (43, 20), (44, 20), (21, 19), (22, 18), (23, 18), (39, 18), (41, 18), (30, 17), (36, 17), (42, 17), (27, 16), (11, 15), (31, 14), (12, 13), (15, 13), (19, 13), (25, 13), (37, 13), (33, 12), (24, 11), (18, 10), (20, 10), (40, 10), (10, 9), (29, 4)]

在 [5] 中:%timeit amber() 10000 次循环,最好的 3 次:每个循环 71.1 我们

在 [6] 中:%timeit ashwc() 1000 次循环,最好的 3 次:每个循环 753 我们

【问题讨论】:

  • 这并不完全相关,但如果您需要按添加键的顺序对字典进行排序,请尝试使用OrderedDict

标签: python


【解决方案1】:

我发现itertools.groupby 在这些情况下非常有用,所以我认为我应该只提一个替代方案。 (实际上,我发现itertools 在很多情况下非常有用,但我有很多函数式编程的历史。)这里的好处是您不必构建单独的字典,这可能会或可能不会提高性能.

    from itertools import groupby

    PairDict= {(19, 6): 13, (2, 29): 10, (38, 8): 20, (38, 5): 5}
    key = lambda i: i[0][0]
    SortedPairDict = groupby(sorted(PairDict.iteritems(), key=key), key=key)

SortOrder 应该可以使用以下方法进行计算:

    SortOrder = [ (k, sum(v[1] for v in g)) for k, g in SortedPairDict ]

我注意到上面较长示例中的列表没有任何特定顺序,所以不确定我是否误解了任何内容。

【讨论】:

    【解决方案2】:
    sortkeys = dict((x[0], index) for index,x in enumerate(SortOrder))
    SortedPairDict = sorted(PairDict.iteritems(),
                            key=lambda x: sortkeys[x[0][0]])
    

    这里的想法是我们真的不想重新发明排序,所以我们希望有一种可以使用 Python 内置 sorted() 函数的格式。

    为此,我们需要sorted() 可以接受的格式的订购信息。最简单的方法是定义一个 Python 已经知道如何排序的“键”,例如一组有序整数。

    在这种情况下,我们通过将 SortOrder 列表中的值映射到它们在该列表中的位置来实现这一点。然后,我们定义我们的 key 函数来简单地查找与元组键的第一个元素对应的 SortOrder 位置。


    >>> sortkeys = dict((x[0], index) for index,x in enumerate(SortOrder))
    >>> SortedPairDict = sorted(PairDict.iteritems(),
    ...                         key=lambda x: sortkeys[x[0][0]])
    >>> SortedPairDict
    [((38, 5), 5), ((38, 8), 20), ((19, 6), 13), ((2, 29), 10)]
    

    【讨论】:

    • 非常感谢它就像一个魅力。我不知道有你提到的更简单的方法。我一直在想需要为操作创建一个函数。从你的cmets那里学到了很多东西。圣诞快乐!
    猜你喜欢
    • 2011-04-03
    • 2023-01-21
    • 2014-06-25
    • 2016-03-07
    • 2018-08-13
    • 1970-01-01
    • 2017-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多