0

I've found several SO posts on similar questions but I'm maybe overthinking my problem.

I'm running a loop. Each iteration returns a dict with the same keys and their own values. I'd like to combine them into a new master dict.

On each loop iteration I can save the results to a list

store_response = [] # will store the results of each iteration here
myloop:
    code here...
    store_response.append(iresponse.copy())

Or I can do:

store_response = {} # will store the results of each iteration here
myloop:
    code here...
    store_response[page_token] = iresponse  # store this iteration and call it whatever string page_token currently is

So I can return either a list of dicts or dict of dicts.

My question is, how can I combine them into just one dict? Tried several for loops but keep hitting errors e.g.:

for d in store_response:
    for key, value in d.iteritems():
        test[key].append(value)
Traceback (most recent call last):
  File "<input>", line 2, in <module>
AttributeError: 'dict' object has no attribute 'iteritems'

Here is how the variable looks in PyCharms variables pane, currently in list form but I could make it a dict: enter image description here

How can I take each dict within store response and create a single master dict?

Doug Fir
  • 19,971
  • 47
  • 169
  • 299
  • If you want them in one dictionary, should the values be a list then for a given key? – rvd Sep 30 '19 at 16:07
  • @rvd the format should be the same as the child elements in the screen. So the master dict should match e.g. `store_response[0]` in terms of structure. Does that asnwer your question? – Doug Fir Sep 30 '19 at 16:09
  • So the keys should just be 0, 1, ... and the values are the child `dict`s seen here? – rvd Sep 30 '19 at 16:11
  • Ah wait. Actually it's the reports. The master dict should just have one key for reports which is the combination of the other 5 – Doug Fir Sep 30 '19 at 16:13
  • Ok - I will respond with an answer then below. – rvd Sep 30 '19 at 16:14
  • `AttributeError: 'dict' object has no attribute 'iteritems'` - Which Python version? Try [`dict.items()`](https://docs.python.org/3/tutorial/datastructures.html#looping-techniques) – wwii Sep 30 '19 at 16:37
  • Possible duplicate of [merging several python dictionaries](https://stackoverflow.com/questions/9415785/merging-several-python-dictionaries) – wwii Sep 30 '19 at 16:40

2 Answers2

1

You are using Python 3, and in Python 3 iteritems has been removed use items instead.

for d in store_response:
    for key, value in d.items():
        test.setdefault(key, [])
        test[key].append(value)
lmiguelvargasf
  • 63,191
  • 45
  • 217
  • 228
  • Hi, I tried with ```for d in store_response: for key, value in d.items(): test[key].append(value) Traceback (most recent call last): File "", line 3, in KeyError: 'reports'``` Any ideas? – Doug Fir Sep 30 '19 at 16:10
  • @DoughFir, what is `test`. I guess this is a dictionary which values are lists. This means that there is no element associated with the key `'reports'`. – lmiguelvargasf Sep 30 '19 at 16:12
  • Test is currently an empty dict ```{}```. I created just to try to house a new master dict – Doug Fir Sep 30 '19 at 16:14
  • @DougFir, I just edited my answer. Use `setdefault` to give a default value (in this case an empty list), when it doesn't have it. – lmiguelvargasf Sep 30 '19 at 16:16
  • Thanks I tried that: ```for d in store_response: for key, value in d.items(): test.setdefault(key, default=[]) test[key].append(value) Traceback (most recent call last): File "", line 3, in TypeError: setdefault() takes no keyword arguments``` – Doug Fir Sep 30 '19 at 16:17
  • @DoughFir, updated, just remove the keyword argument `default`. – lmiguelvargasf Sep 30 '19 at 16:18
  • Thanks that ran but the result is not what I expected. After running that test is a dict that contains one item 'reports' and reports is a list of the original dicts. What I meant was that there would no longer be 5 nested dicts just one 'reports' that contains the accumulated values of the original 5? – Doug Fir Sep 30 '19 at 16:21
  • @DougFir, This is a bit different from what you asked originally. – lmiguelvargasf Sep 30 '19 at 16:23
  • Sorry if I was not clear I appreciate the time you put in to answer – Doug Fir Sep 30 '19 at 16:24
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/200180/discussion-between-lmiguelvargasf-and-doug-fir). – lmiguelvargasf Sep 30 '19 at 16:24
1

You could try a pattern like:

from collections import defaultdict
store_response = defaultdict(list)
for _ in loop:
    # Assuming the loop provides the key and value
    store_response[key].append(value)

This will result in a dict with one key that collapses all values for that key as a list (in your use case since your dictionaries only have one key - this solution works for arbitrarily many keys like 'reports').

rvd
  • 558
  • 2
  • 9