【问题标题】:Sum of all the values in a dictionary which contains the item in the key包含键中项目的字典中所有值的总和
【发布时间】:2013-12-09 21:50:38
【问题描述】:

给定一个字典和一个字符串作为参数,返回一个新字典,其中包含指定为类别的项目(第二个参数,'city'、'sport'、'name' 之一)作为键和它的关联值。如果该项目不止一次出现,则取值的总和。

例如。

>>> get_wins_by_category(d, 'city')
{'Toronto': 34, 'Ottawa': 45}
>>> get_wins_by_category(d, 'sport')
{'basketball': 31, 'hockey': 48}
>>> get_wins_by_category(d, 'name')
{'Raptors': 10, 'Blues': 21, 'Senators': 45, 'Leafs': 3}

到目前为止我得到了什么:

d = {('Raptors', 'Toronto', 'basketball'): 10,
     ('Blues', 'Toronto', 'basketball'): 21,
     ('Senators', 'Ottawa', 'hockey'): 45,
     ('Leafs', 'Toronto', 'hockey'): 3}

def get_wins_by_category(dct, category):
    new_dict = {}
    if category == 'city':
        for key in dct.keys():
            new_dict[key[1]] = #todo
    elif category == 'sport':
        for key in dct.keys():
            new_dict[key[2]] = #todo
    elif category == 'name':
        for key in dct.keys():
            new_dict[key[0]] = #todo
    return new_dict

我的问题是等号后写什么。我知道,如果该项目不止一次出现,它采用包含该项目的所有值的总和,但我不知道如何将其编写为代码。另请注意,三元组将始终按以下顺序排列:姓名、城市、运动。

【问题讨论】:

  • 我从来没有想过使用元组作为字典中的键。

标签: python dictionary key


【解决方案1】:

使用collections.defaultdict,不需要if-else:

from collections import defaultdict
def get_wins_by_category(team_to_win, category):

    d = {'name':0, 'city':1, 'sport':2}
    dic = defaultdict(int)
    for k, v in team_to_win.items():
        dic[k[d[category]]] += v
    return dic
... 
>>> get_wins_by_category(d, 'city')
defaultdict(<type 'int'>, {'Toronto': 34, 'Ottawa': 45})
>>> get_wins_by_category(d, 'sport')
defaultdict(<type 'int'>, {'basketball': 31, 'hockey': 48})
>>> get_wins_by_category(d, 'name')
defaultdict(<type 'int'>, {'Senators': 45, 'Blues': 21, 'Raptors': 10, 'Leafs': 3})

另一种选择是collections.Counter

from collections import Counter
def get_wins_by_category(team_to_win, category):
    #index each category points to
    d = {'name':0, 'city':1, 'sport':2}
    dic = Counter()       
    for k, v in team_to_win.items():
        dic[k[d[category]]] += v
    return dic
... 
>>> get_wins_by_category(d, 'city')
Counter({'Ottawa': 45, 'Toronto': 34})
>>> get_wins_by_category(d, 'sport')
Counter({'hockey': 48, 'basketball': 31})
>>> get_wins_by_category(d, 'name')
Counter({'Senators': 45, 'Blues': 21, 'Raptors': 10, 'Leafs': 3})

【讨论】:

  • 如果你只想数数,为什么不使用Counterdefaultdict(int) 更难理解,代码更多,输出可读性更低。
  • 谢谢 Ashwini,但是如果我不使用导入(在考试中使用导入不是一个选项)我将如何处理这个问题?我们还没有使用导入,所以集合等对我来说是新的。
  • @Sc4r 只需将 dic 替换为简单的 dict({}) 并将此 dic[k[d[category]]] += v 行替换为:dic[k[d[category]]] = v + dic.get(k[d[category]], 0)
【解决方案2】:

使用错误的数据结构总是会让你的代码更难写、更难读,而且通常也会更高效地运行。

如果您想按值查找某些内容,请使用以该值作为键的 dict(或命名元组),不要遍历整个列表并逐个搜索。如果您需要创建多个 dicts,请执行此操作。

例如:

from collections import Counter
teams, cities, sports = Counter(), Counter(), Counter()
for keys, score in d.items():
    team, city, sport = keys
    teams[team] += score
    cities[city] += score
    sports[sport] += score
categories = {'team': teams, 'city': cities, 'sport': sports}

现在你的代码很简单:

def get_wins_by_category(category):
    return categories[category]

或者,或者,保留每个分数的所有分数,这样除了对分数求和(例如,平均分数)之外,您还可以做其他事情:

from collections import Counter
teams, cities, sports = defaultdict(list), defaultdict(list), defaultdict(list)
for keys, score in d.items():
    team, city, sport = keys
    teams[team].append(score)
    cities[city].append(score)
    sports[sport].append(score)
categories = {'team': teams, 'city': cities, 'sport': sports}

def get_wins_by_category(category):
    return {key: sum(scores) for key, scores in categories[category].items()}

def get_avg_wins_by_category(category):
    return {key: sum(scores)/len(scores) 
            for key, scores in categories[category].items()}

【讨论】:

    【解决方案3】:
    if category == 'city':
            for key, value in dct.items():
                new_dict[key[1]] += value
    

    你明白了..

    【讨论】:

      【解决方案4】:

      以下通过在cats 中定义输入来消除对if: 块的需求

      d = {('Raptors', 'Toronto', 'basketball'): 10,
           ('Blues', 'Toronto', 'basketball'): 21,
           ('Senators', 'Ottawa', 'hockey'): 45,
           ('Leafs', 'Toronto', 'hockey'): 3}
      
      cats = ("team", "city", "sport")
      
      def get_wins_by_category(d, cats, cat):
          if cat in cats:    
              return {t: sum(v for k, v in d.items() if t in k) 
                      for t in set(key[cats.index(cat)] for key in d)}
      

      【讨论】:

        猜你喜欢
        • 2012-12-18
        • 2015-11-15
        • 1970-01-01
        • 2022-08-21
        • 2011-02-12
        • 2020-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多