2012-12-24 57 views
0

我在下面關鍵的字典,值格式重新排序詞典:基於特定順序

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具有多個具有相同第一個元素的元組,則它的排序順序可以是任意的。需要首先對其進行排序,在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分析琥珀和阿什維尼的解決方案

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琥珀色() 10000圈,最好的3:71.1每循環

我們在文獻[6 ]:%timeit ashwc() 1000次循環,最好的3:753每回路

+1

這不是完全相關的,但是如果你需要一本字典的順序進行排序的是添加鍵,嘗試使用[OrderedDict](http://docs.python.org/2/library/collections的.html)。 – Natan

回答

5
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列表中的值映射到它們在該列表中的位置來執行此操作。然後我們定義按鍵功能簡單地查找對應的元組鍵的第一個元素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)] 
+0

非常感謝你,它的工作就像一個魅力。正如你所提到的,我不知道有一種更簡單的方法。我一直在想的是需要爲操縱創建一個功能。從你的評論中學到了很多東西。聖誕節快樂! –

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 ] 

我注意到,在上面的詳細示例的名單是不以任何特定的順序,所以不知道如果我誤解了什麼。