0

I have a list of dictionaries with identical keys. Furthermore, there are only two 'key: value' pairs per dictionary. I want to convert the list of dictionaries to a single dictionary with two keys, each representing a list value. Such that values of identical keys reside in one list.

I came up with the following approach, which by the way works perfectly fine. But I am hoping to know if there is any better practical approach.

The List of Dictionaries:

my_list = [{'old_price': None, 'price': '5,75'}, {'old_price': None, 'price': '5,90'}, {'old_price': None, 'price': '5,95'}, {'old_price': None, 'price': '10,15'}, {'old_price': None, 'price': '19,90'}, {'old_price': None, 'price': '34,90'}, {'old_price': None, 'price': '46,50'}, {'old_price': None, 'price': '24,90'}]

List of Dictionaries to Dictionary of Lists:

single_dict = {"old_price": [item['old_price'] for item in my_list], "price":[item['price'] for item in my_list]}

The Resulted Dictionary:

{'old_price': [None, None, None, None, None, None, None, None], 'price': ['5,75', '5,90', '5,95', '10,15', '19,90', '34,90', '46,50', '24,90']}
Stef
  • 13,242
  • 2
  • 17
  • 28
Uğur Eren
  • 163
  • 3
  • 11
  • Is this post help you : https://stackoverflow.com/questions/38987/how-do-i-merge-two-dictionaries-in-a-single-expression-taking-union-of-dictiona – Cyrille Pontvieux Aug 10 '21 at 09:52
  • 2
    What don't you like about your solution? To me it looks like it's good – Essay97 Aug 10 '21 at 09:55
  • @CyrillePontvieux Do any of the answers there show how to make a list of all the values from the dictionaries? It looks like they just overwrite the common keys. – Barmar Aug 10 '21 at 09:58
  • @barmar that answer OP question: how to merge multiple dictionaries into one ; not how to extract only value, but the solution is almost the same, just use a set or list instead of a dict when iterating/deconstruct – Cyrille Pontvieux Aug 10 '21 at 10:02
  • I checked the post but it doesn't seem to work for me. @CyrillePontvieux – Uğur Eren Aug 10 '21 at 10:37

4 Answers4

0

With the use of defaultdict, you can make the algorithm O(N), looping over the list one single time.

>>> my_list = [{'old_price': None, 'price': '5,75'}, {'old_price': None, 'price': '5,90'}, {'old_price': None, 'price': '5,95'}, {'old_price': None, 'price': '10,15'}, {'old_price': None, 'price': '19,90'}, {'old_price': None, 'price': '34,90'}, {'old_price': None, 'price': '46,50'}, {'old_price': None, 'price': '24,90'}]

>>> from collections import defaultdict
>>> d = defaultdict(list)  # will create a list for every missing entry
>>> for adict in my_list:
...    for key, value in adict.items():
...       d[key].append(value)
...    
>>> d
defaultdict(<class 'list'>, {'old_price': [None, None, None, None, None, None, None, None], 'price': ['5,75', '5,90', '5,95', '10,15', '19,90', '34,90', '46,50', '24,90']})

If you know beforehand the keys that you need, you can swap the loop with fixed assignments (however the time cost is very small):

>>> for adict in my_list:
...    d["old_price"].append(adict["old_price"])
...    d["price"].append(adict["price"])
...
crissal
  • 2,547
  • 7
  • 25
  • *"With the use of `defaultdict`, you can make the algorithm O(N)"*. I love `defaultdict`, but it's not magic, and doesn't really "make" anything O(N). In fact, the solution suggested by the OP in their question is already O(N). – Stef Aug 10 '21 at 10:30
  • It's not magic, but if a key is missing you will have a default "blank" element. The algorithm proposed by OP is O(N*M), where M is the number of keys extracted from the small dictionaries - in this case M=2. – crissal Aug 10 '21 at 10:41
  • And you're claiming that your code is **not** O(N*M)? – Stef Aug 10 '21 at 10:46
  • The first version provided is indeed O(N*M); however this is not true for the second one. – crissal Aug 10 '21 at 13:39
0

Iterate to your dict and then create a new dict with a checker whether is already created or not.

my_list = [{'old_price': None, 'price': '5,75'}, {'old_price': None, 'price': '5,90'}, {'old_price': None, 'price': '5,95'}, {'old_price': None, 'price': '10,15'}, {'old_price': None, 'price': '19,90'}, {'old_price': None, 'price': '34,90'}, {'old_price': None, 'price': '46,50'}, {'old_price': None, 'price': '24,90'}]
result = {}
for each_dict in my_list:
    for k in each_dict:
        if (k in result): 
            result[k].append(each_dict[k])
        else:
            result[k] = [each_dict[k]]

print(result)

Output:

{'old_price': [None, None, None, None, None, None, None, None], 'price': ['5,75', '5,90', '5,95', '10,15', '19,90', '34,90', '46,50', '24,90']}
Rizquuula
  • 578
  • 5
  • 15
0

Processing data, I am used to using pandas...

import pandas as pd

my_list = [{'old_price': None, 'price': '5,75'}, {'old_price': None, 'price': '5,90'},
           {'old_price': None, 'price': '5,95'}, {'old_price': None, 'price': '10,15'},
           {'old_price': None, 'price': '19,90'}, {'old_price': None, 'price': '34,90'},
           {'old_price': None, 'price': '46,50'}, {'old_price': None, 'price': '24,90'}]

df = pd.DataFrame(my_list)

columns = df.columns.tolist()
data = {}
// merge same key
for key in columns:
    data[key] = df[key].tolist()

print(data)

Trock
  • 546
  • 2
  • 13
0

Try this:

values = list(map(list, zip(*[item.values() for item in my_list])))
single_dict = { 'old_price':values[0], 'price':values[1] }
Sup
  • 191
  • 5