2017-11-04 141 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

相关问题