2017-02-22 41 views
1

У меня есть эта структура данных в Python:питона вложенными ДИКТ в группе массива сумме

result = { 
    "data": [ 
     { 
      "2015-08-27": { 
       "clicks": 10, 
       "views":20 

      } 
     }, 
     { 
      "2015-08-28": { 
       "clicks": 6, 
      } 
     } 
    ] 
} 

Как я могу добавить элементы каждого словаря? Выход должен быть:

{ 
    "clicks":16, # 10 + 6 
    "views":20 
} 

Я ищу решение Pythonic для этого. Любые решения, использующие счетчик, приветствуются, но я не могу его реализовать.

Я попытался это, но я получаю сообщение об ошибке:

counters = [] 
for i in result: 
    for k,v in i.items(): 
     counters.append(Counter(v)) 

sum(counters) 
+1

Вы, вероятно, получили все те вниз голоса потому что вы не показали свою собственную попытку кода. Помните, что даже сломанный соответствующий код лучше, чем никакого кода. –

+1

Я сделал редактирование, которое я пробовал. я думал, что мое неправильное решение не имеет значения – anekix

+1

Это намного лучше!Показывая нам неправильное решение, мы показываем, что вы пытались выполнить эту работу, и вы не ленитесь. Но что более важно, плохой код помогает нам видеть ошибки в вашем понимании того, как работает Python, и это помогает нам писать ответы, которые могут исправить эти недоразумения. –

ответ

1

Ваш код был очень близок к работоспособному решению, и мы можем заставить его работать с несколькими важными изменениями. Самое важное изменение заключается в том, что нам нужно перебирать элемент "data" в result.

from collections import Counter 

result = { 
    "data": [ 
     { 
      "2015-08-27": { 
       "clicks": 10, 
       "views":20 

      } 
     }, 
     { 
      "2015-08-28": { 
       "clicks": 6, 
      } 
     } 
    ] 
} 

counts = Counter() 
for d in result['data']: 
    for k, v in d.items(): 
     counts.update(v) 

print(counts) 

выход

Counter({'views': 20, 'clicks': 16}) 

можно упростить, что мало, потому что нам не нужны ключи.

counts = Counter() 
for d in result['data']: 
    for v in d.values(): 
     counts.update(v) 

код вы вывесили составляет список счетчиков, а затем пытается подвести их. Я думаю, что это также действительная стратегия, но, к сожалению, встроенный модуль sum не знает, как добавить счетчики вместе. Но мы можем сделать это, используя functools.reduce.

from functools import reduce 

counters = [] 
for d in result['data']: 
    for v in d.values(): 
     counters.append(Counter(v)) 

print(reduce(Counter.__add__, counters)) 

Однако, я подозреваю, что первая версия будет быстрее, особенно, если есть много dicts добавить вместе. Кроме того, эта версия потребляет больше оперативной памяти, поскольку она хранит список всех счетчиков.


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

print(sum(counters, Counter())) 

Мы можем объединить это в однострочник, устраняя список, используя выражение генератора вместо:

from collections import Counter 

result = { 
    "data": [ 
     { 
      "2015-08-27": { 
       "clicks": 10, 
       "views":20 

      } 
     }, 
     { 
      "2015-08-28": { 
       "clicks": 6, 
      } 
     } 
    ] 
} 

totals = sum((Counter(v) for i in result['data'] for v in i.values()), Counter()) 
print(totals) 

выхода

Counter({'views': 20, 'clicks': 16}) 
+0

Если я моляю итерации и сумме, используя +, он не показывает ошибки, но используя sum(), если show + не может использоваться с помощью счетчика каких-либо идей о том, почему это происходит? – anekix

+0

Счетчик уже имеет значение, вам не нужно ничего вручную суммировать. –

+0

@anekix Я добавил дополнительную информацию в свой ответ об этом. –

0

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

res = {} 
for x in my_dict['data']: 
    for y in x: 
     for t in x[y]: 
      res.setdefault(t, 0) 
      res[t] += x[y][t] 
print(res) # {'views': 20, 'clicks': 16}