2017-11-04 80 views
1

任何人都可以使用此功能嗎?我沒有線索寫代碼,我在函數體中寫的是錯誤的。鍵入字典:值爲列表

def get_quantities(table_to_foods: Dict[str, List[str]]) -> Dict[str, int]: 

    """The table_to_foods dict has table names as keys (e.g., 't1', 't2', and 
    so on) and each value is a list of foods ordered for that table. 

    Return a dictionary where each key is a food from table_to_foods and each 
    value is the quantity of that food that was ordered. 

    >>> get_quantities({'t1': ['Vegetarian stew', 'Poutine', 'Vegetarian stew'], 
    't3': ['Steak pie', 'Poutine', 'Vegetarian stew'], 't4': ['Steak pie', 'Steak pie']}) 
    {'Vegetarian stew': 3, 'Poutine': 2, 'Steak pie': 3}  
    """ 

    food_to_quantity = {} 
    for t in table_to_foods: 
     for i in table_to_foods[t]: 
      if i in table_to_foods[t]: 
       food_to_quantity[i] = food_to_quantity[i] + 1 

    return food_to_quantity 

回答

1

使用Counters

from collections import Counter 

def get_quantities(table_to_foods: Dict[str, List[str]]) -> Dict[str, int]: 
    return dict(Counter(x for v in table_to_foods.values() for x in v)) 

您可能沒有從做dictCounterCounterdict一個子類),但是我在這裏做,所以你的類型是相同的

+0

感謝您的幫助。由於這是我的第一個計算機科學課程,而且我還沒有學習計數器方法。你認爲你有辦法在沒有櫃檯的情況下解決這個功能嗎?我的教授也希望我返回food_to_quantity。如果我問得太多,我很抱歉。 –

+1

以這種方式使用'sum'是很昂貴的,因爲它使得許多臨時的'Counter'對象僅僅在下一步後丟棄它們('sum'特殊情況[拒絕]'str'以防止相同的低效率,但不能識別它在一般情況下)。重做它爲'dict(counter(x for v in table_to_foods.values()for v in v))',即使是中等大小的輸入,你也會大大減少運行時間(即使是三個密鑰的小字典,每個值使用'sum'的時間是使用帶有genexpr輸入的單個'Counter'的5倍,並且隨着輸入放大,它只會變差。 – ShadowRanger

+0

雖然我不知道@ShadowRanger的方法。感謝你們對我的幫助。 –

2

無數據庫計數項目的常用方法是使用python get()函數

foods = { 
    't1': ['banana', 'apple', 'banana'], 
    't2': ['orange', 'apple', 'banana'], 
    't3': ['apple', 'grapes', 'banana'] 
    } 

def get_quantities(foodLists): 
    totals = {} 
    for foodList in foodLists.values(): 
     for food in foodList: 
      totals[food] = totals.get(food, 0) + 1 
    return totals 

print(get_quantities(foods)) 

它打印:

{'banana': 4, 'apple': 3, 'orange': 1, 'grapes': 1}

+2

如果你不使用'k',你不妨使用'foodLists.values'視圖來代替'items' –

+0

該代碼行中的k是什麼意思? –

+0

@guanyuma:這是'dict'的關鍵。你不會使用它,這就是爲什麼Patrick建議刪除它(並且只迭代'values',而不是來自'items'的鍵/值對)。 – ShadowRanger

0

試試這個:

def get_quantities(table_to_foods): 
    food_to_quantity = {} 
    for table in table_to_foods.values(): 
     for food in table: 
      food_to_quantity[food] = food_to_quantity.get(food, 0) + 1 
    return food_to_quantity 

您可以使用.values()來獲得在字典中的值,然後通過每個項目迭代。如果食物在字典中,則將其值加1,如果不是,則將該食物作爲字典中的新項目添加。

get_quantities({ 
    't1': ['Vegetarian stew', 'Poutine', 'Vegetarian stew'], 
    't2': ['Steak pie', 'Poutine', 'Vegetarian stew'], 
    't3': ['Steak pie', 'Steak pie'] 
    }) 

應輸出隨後如果印刷:

{'Poutine': 2, 'Steak pie': 3, 'Vegetarian stew': 3} 

更多字典: https://docs.python.org/3/tutorial/datastructures.html#dictionaries

+0

謝謝你幫助它工作。在代碼中'if food in food_to_quantity'。這是我需要如何將鍵分配到一個空的DIC? –

+0

'如果food_to_quantity中的食物'檢查食物是否已經在字典中,如果是,那麼它會將該食物的當前值加1。如果不是,那麼else語句將賦值爲1的新密鑰。您也可以使用.get(),如上面 –

+0

以上的人所述。謝謝您的幫助。 –

4

又一個的情況下,做你喜歡使用itertools.chaincollections.Counter方式:

from itertools import chain 
from collections import Counter 

dict(Counter(chain.from_iterable(foods.values()))) 
#or Simply 
dict(Counter(chain(*foods.values()))) 

#Output: 
#{'apple': 3, 'banana': 4, 'grapes': 1, 'orange': 1} 
+0

這幾乎肯定是最有效的解決方案(特別是在現代Python 3中,其中'Counter'使用C加速器來幫助計算輸入迭代次數,所以使用'Counter'+'chain'意味着輸入的全部消耗被推到CPython上的C層)。 – ShadowRanger