2017-05-14 27 views
1

我想弄清楚如何創建一個帶有值(這是元組)的字典的排序表示,使用自定義比較器在Python 3中的值,以通用的方式如何創建字典的排序表示,使用元組值的自定義比較器?

我看了這些題目,但我仍然在努力:

Sort a Python dictionary by value

How to use a custom comparison function in Python 3?

作爲具體的例子,一個可以考慮我試圖解決的問題,「獲取按總成本排序的產品列表,給出一個字典,其中包含客戶在結帳時的產品(關鍵),以及每個產品的數量和成本(以2元組形式存儲)。 2,人們可以使用這樣的東西:

checkout_dict = {'Apples': (1, 3), 'Oranges': (3, 3), 'Grapes': (7, 1), 
       'Cheese': (10, 1), 'Crackers': (4, 4)} 


from operator import itemgetter 


def sort_dict(dict, comparison_func): 
    return sorted(dict.iteritems(), key=itemgetter(1), 
        cmp=comparison_func) 


def cmp_total_cost(product_data_1, product_data_2): 
    total_product_cost_1 = (product_data_1[0]) * (product_data_1[0]) 
    total_product_cost_2 = (product_data_2[0]) * (product_data_2[0]) 
    return total_product_cost_2 - total_product_cost_1 


print sort_dict(checkout_dict, cmp_total_cost) 

預期的輸出會是這個樣子:

[('Crackers', (4, 4)), ('Cheese', (10, 1)), ('Oranges', (3, 3)), 
('Grapes', (7, 1)), ('Apples', (1, 3))] 

但是在Python 3中,cmp參數sorted被棄用,取而代之的是我們需要包括行爲作爲key參數的一部分。

我知道我們需要使用類似於cmp_to_key function from the functools module的東西,但我無法圍繞如何將所有東西都推廣到一邊。我對itemgetter(1)如何與cmp_to_key函數和自定義比較函數結合感到困惑。

此外,我明白,用上面的例子,我可以很容易地只是循環字典第一,並計算總成本,然後做排序,但我正在尋找一個通用的解決方案,我可以申請許多不同類型的比較。

注意

我也想這是儘可能高性能。我發現了一些信息,使用operator.itemgetter真的可以幫助加快速度吧: Sorting Dictionaries by Value in Python (improved?)

+0

爲了長話短說,'sorted(checkout_dict,key = magic_function)'的預期輸出是什麼? – DeepSpace

+0

在上面給出的例子中,它將是一個元組''(product_name,(number_in_checkout,value))''的列表,無論magic_function如何排序。 – Jinglesting

+0

但是按什麼順序? – DeepSpace

回答

0

如果你只是想獲得一個元組列表,第一元素時代的第二個元素有序,這將做到:

sorted(checkout_dict.items(), key=lambda item: item[1][0] * item[1][1]) 

# [('Apples', (1, 3)), ('Grapes', (7, 1)), ('Oranges', (3, 3)), ('Cheese', (10, 1)), 
# ('Crackers', (4, 4))] 

# or in the other way around 
sorted(checkout_dict.items(), key=lambda item: item[1][0] * item[1][1], reverse=True) 
# [('Crackers', (4, 4)), ('Cheese', (10, 1)), ('Oranges', (3, 3)), ('Grapes', (7, 1)), 
# ('Apples', (1, 3))] 
+0

感謝DeepSpace,我正在尋找一種通用的方法來對任何使用元組值的元素進行此操作,我可以將其指定爲參數。也許我給出的例子太具體了。這在2.x中似乎很容易,但在3中不確定! – Jinglesting

+0

@Jinglesting我不確定我在這裏看到的問題是誠實的。而不是從'cmp'函數返回-1,0,1(對於<, =, >),您只需返回* actual *值以與'key'函數進行比較。然後Python會計算出如何將返回值與其他值進行比較。 – DeepSpace

+0

此外,lambda函數的問題是函數調用的所有開銷(這也是我給出的2.7示例中的一個問題)。 「operator.itemgetter」有助於避免這些情況,但我不確定可以根據我的要求利用這一點。你的解決方案可以寫成「itemgetter」嗎? – Jinglesting

相關問題