2013-12-09 4 views
3

Учитывая словарь и строку в качестве параметров, верните новый словарь, содержащий элемент, указанный в качестве категории (второй параметр, один из «города», «спорт» ',' name ') в качестве ключа и связанного с ним значения. Если имеется более одного вхождения элемента, чем принимать сумму значений.Сумма всех значений в словаре, которая содержит элемент в ключе

Ex.

>>> 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 

Проблема у меня есть, что писать после знака равенства. Я знаю, что если есть несколько элементов элемента, которые берут сумму всех значений, содержащих этот элемент, но я не знаю, как записать его в качестве кода. Также обратите внимание, что 3-кортеж всегда будет в таком порядке: имя, город, спорт.

+0

Я никогда не думал об использовании кортежа в качестве ключа в словаре. – TehTris

ответ

2

Использование collections.defaultdict, нет, если-то еще требуется:

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}) 
+1

Если вы хотите просто подсчитать, почему бы не использовать 'Counter'? «Defaultdict (int)» сложнее понять, и больше кода, и производит менее читаемый вывод. – abarnert

+0

Спасибо Ashwini, однако, если бы я сделал это без импорта (на экзамене с использованием импорта не вариант), как бы я к этому подошел? Мы еще не использовали импорт, поэтому коллекции и т. Д. Новы для меня. – Sc4r

+0

@ Sc4r Просто замените 'dic' простым dict (' {} ') и замените эту строку' dic [k [d [category]]] + = v' следующим образом: 'dic [k [d [category]]] = v + dic.get (k [d [category]], 0) ' –

0

Следующая устраняет необходимость в if: блоков путем определения входов в cats

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)} 
0
if category == 'city': 
     for key, value in dct.items(): 
      new_dict[key[1]] += value 

Вы получаете пункт ..

1

Использование неправильной структуры данных всегда делает код более сложным, чтобы писать, и читать, и часто для эффективной работы, а также.

Если вы хотите посмотреть что-то по значению, используйте dict (или namedtuple) с этим значением в качестве ключа, не перебирайте весь список и не ищите по одному. Если вам нужно создать несколько 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()} 
Смежные вопросы