how to convert list of dict to dict
Asked Answered
N

11

84

How to convert list of dict to dict. Below is the list of dict

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]

to

data = {'John Doe': {'name': 'John Doe', 'age': 37, 'sex': 'M'},
        'Lisa Simpson': {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        'Bill Clinton': {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}}
Northing answered 8/3, 2011 at 17:51 Comment(0)
O
110

A possible solution using names as the new keys:

new_dict = {}
for item in data:
   name = item['name']
   new_dict[name] = item

With python 3.x you can also use dict comprehensions for the same approach in a more nice way:

new_dict = {item['name']:item for item in data}

As suggested in a comment by Paul McGuire, if you don't want the name in the inner dict, you can do:

new_dict = {}
for item in data:
   name = item.pop('name')
   new_dict[name] = item
Ocreate answered 8/3, 2011 at 17:58 Comment(6)
That will leave an extra name field, which may or may not be what the user wants. (i.e., the new dictionary looks like {'Lisa Simpson': {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'} ...})Drachma
add "item.pop('name')" after assigning name, and then you won't get the extra name field.Lowelllowenstein
@Platinum — That's actually pretty common when using a dictionary as a lookup table. Another data structure can then refer to the dictionary value directly without losing the key (as opposed to storing the key and looking it up in the table each time it's accessed).Kickshaw
@Platinum Azure: you're right, but the OP question does not give any clue on this respect. This is only a posible solution. I have used similar dicts (use of redundant fields) in some applications when I want to obtain the full info from a subject using a value in the subject info. Obviously other primary keys could also be used or, as sugested, to eliminate the redundant key from the original dict.Ocreate
What if the data is dynamic and there is not fixed name key? Is there a way to solve that? I am facing a similar problem only in my case the data consists of MongoDB queries so it is not static.Nimiety
The question was simply to convert a list of dictionaries to a dictionary. I don't think the solution suggested does not produce the intended output.Despicable
A
55

With python 3.3 and above, you can use ChainMap

A ChainMap groups multiple dicts or other mappings together to create a single, updateable view. If no maps are specified, a single empty dictionary is provided so that a new chain always has at least one mapping.

from collections import ChainMap

data = dict(ChainMap(*data))
Adenoidectomy answered 26/6, 2018 at 16:47 Comment(3)
is this guaranteed to be faster? Previous answers iterate on the whole list, so it is O(n), is ChainMap less than this?Aylsworth
it's returning only first entry of row as dict.Simard
Note that, as @gudé commented, ChainMap is not efficient.Silvester
D
41

If the dicts wouldnt share key, then you could use:

dict((key,d[key]) for d in data for key in d)

Probably its better in your case to generate a dict with lists as values?

newdict={}
for k,v in [(key,d[key]) for d in data for key in d]:
  if k not in newdict: newdict[k]=[v]
  else: newdict[k].append(v)

This yields:

>>> newdict
`{'age': [37, 17, 57], 'name': ['John Doe', 'Lisa Simpson', 'Bill Clinton'], 'sex': ['M', 'F', 'M']}`
Davon answered 8/3, 2011 at 18:10 Comment(0)
N
15

Try this approach:

{key: val} for k in data for key, val in k.items())
Nicoline answered 18/9, 2018 at 8:13 Comment(0)
D
6

Let's not over complicate this:

simple_dictionary = dict(data[0])
Deadening answered 27/7, 2020 at 14:36 Comment(1)
it's not the solution but it helped in my question so i am upvoting thisSeaquake
C
2

Perhaps you want the name to be the key? You don't really specify, since your second example is invalid and not really meaningful.

Note that my example removes the key "name" from the value, which may be desirable (or perhaps not).

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
newdata = {}
for entry in data:
    name = entry.pop('name') #remove and return the name field to use as a key
    newdata[name] = entry
print newdata
##{'Bill Clinton': {'age': 57, 'sex': 'M'},
## 'John Doe': {'age': 37, 'sex': 'M'},
## 'Lisa Simpson': {'age': 17, 'sex': 'F'}}
print newdata['John Doe']['age']
## 37
Carboy answered 8/3, 2011 at 18:5 Comment(1)
That depends on how you interpret Simpsons Time. After all, if she was 8 when the show started in 1989, she'd be 29 or 30 today… :-)Kickshaw
G
1

My 5 cents, didn't like any of answers. here is how to convert list of dicts to flat dict.

from functools import reduce
list_of_dicts = [{'hello': 1}, {'world': 2}]
answer = reduce(lambda union, next_dict: union.update(next_dict) or union, 
                list_of_dicts, {})

Result:

{'hello': 1, 'world': 2}

And here is how to convert to nested dict by getting item:

import operator, json
data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
answer = dict(zip(map(operator.itemgetter('name'), data), data))
print(json.dumps(answer, indent=2))

Result:

{
  "John Doe": {
    "name": "John Doe",
    "age": 37,
    "sex": "M"
  },
  "Lisa Simpson": {
    "name": "Lisa Simpson",
    "age": 17,
    "sex": "F"
  },
  "Bill Clinton": {
    "name": "Bill Clinton",
    "age": 57,
    "sex": "M"
  }
}
Galengalena answered 18/2, 2022 at 15:25 Comment(3)
what would be the output of such an approach, it is halfway answered.Silvio
@Silvio it would make a union of all dicts, sequentially, with updatesGalengalena
returns only the first itemWitty
C
1

An alternative approach with list comprehension where the key 'name' is not present in the item value.

{ item['name'] : {k:item[k] for k in item.keys() if k != 'name'} for item in data}

Output:

data = {'John Doe': {'age': 37, 'sex': 'M'},
        'Lisa Simpson': {'age': 17, 'sex': 'F'},
        'Bill Clinton': {'age': 57, 'sex': 'M'}}

Note: we save memory here as we do not have the key value duplicated, but there is some computation price (inner loop over the keys). In this example, it is worth doing it as we save significant memory.

Corpus answered 31/12, 2023 at 9:2 Comment(0)
I
0

Just in case you wanted a functional alternative (also assuming the names are wanted as the new keys), you could do

from toolz.curried import *

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]

newdata = pipe(data, 
               map(lambda x: {x['name']: dissoc(x, 'name')}),
               lambda x: merge(*x)
)

print(newdata)
Infant answered 14/11, 2019 at 18:15 Comment(0)
K
0
import pandas as pd
data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]

print(pd.DataFrame(data).to_dict())
Krishnakrishnah answered 22/12, 2021 at 10:16 Comment(1)
Pandas seems like overkill hereManiemanifest
T
0

Answer provided by Python King (simple as this print({obj['name']:obj for obj in data}))

data = [{'name': 'John Doe', 'age': 37, 'sex': 'M'},
        {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
        {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}]
# answer        
print({obj['name']:obj for obj in data})

result:

     {
      'John Doe': {'name': 'John Doe', 'age': 37, 'sex': 'M'}, 
      'Lisa Simpson': {'name': 'Lisa Simpson', 'age': 17, 'sex': 'F'},
      'Bill Clinton': {'name': 'Bill Clinton', 'age': 57, 'sex': 'M'}
     }






Nice ex also in one answers but how it done python way simple
listofdicts = [
     {1:2,3:4},
     {5:6,7:9},
     {10:8,13:22}
]

old = {}
for x in listofdicts:
    old = {**old, **x}
# not dict not repeat properties
print(old)

result: {1: 2, 3: 4, 5: 6, 7: 9, 10: 8, 13: 22}

# important not dict not allow repeat property so if repeated property the prop and val will be last one found

more ideas

y = {}
for x in [{dict1['prop']:dict1['val']} for dict1 in [{'prop': 'a', 'val': '1'},{'prop': 'b', 'val': '2'}]]:
    y = {**y, **x}
print(y)

example 2

test = {'old': 1}
test = {**old, **{'new': 2}}

result: {'a': '1', 'b': '2'}

complex example one property only dicts

print({list(testit.items())[0][0]:list(testit.items())[0][1] for testit in [{dict1['prop']:dict1['val']} for dict1 in [{'prop': 'a', 'val': '1'},{'prop': 'b', 'val': '2'}]]})

result: {'a': '1', 'b': '2'}

more clear done above

print({ obj['info']:obj['info2'] for obj in [{'info': 'title1', 'info2': 'date1'}, {'info': 'title2', 'info2': 'date2'}]})
Toil answered 26/2 at 13:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.