简体   繁体   中英

Convert list of tuples to dictionary with multiple dict values for a key

My list of tuples:

list = [('WALMART', '601 12th Avenue Northeast',916523), 
('WALMART SHARED', '1953 west brown street',916523)]

Wanted to Convert the list of tuples to Dictionary as shown below:

dict =
    {
        916523: [{
                'cancmpname': 'WALMART',
                'canaddress': '601 12th Avenue Northeast',
            },
            {
                'cancmpname': 'WALMART SHARED',
                'canaddress': '1953 west brown street',

            },
        ]
    }

My code so far:

dict = {}
for result in list:
      dict[result[2]]={}
      dict[result[2]]['cmpname']=result[0]
      dict[result[2]]['cmpaddress']=result[1]

This converts the list into a dictionary with the latest value it doesn't append both the results as dictionary array values

result from my code:

dict =
    {
        916523: {
                'cancmpname': 'WALMART SHARED',
                'canaddress': '1953 west brown street',

            }

    }

You can use itertools.groupby :

import itertools
l = [('WALMART', '601 12th Avenue Northeast',916523), ('WALMART SHARED', '1953 west brown street',916523)]
final_data = {a:[dict(zip(['cancmpname', 'canaddress'], i[:-1])) for i in b] for a, b in itertools.groupby(l, key=lambda x:x[-1])}

Output:

{916523: [{'canaddress': '601 12th Avenue Northeast',
       'cancmpname': 'WALMART'},
      {'canaddress': '1953 west brown street',
       'cancmpname': 'WALMART SHARED'}]}

You can use collections.defaultdict for an O(n) solution.

from collections import defaultdict

lst = [('WALMART', '601 12th Avenue Northeast',916523), 
       ('WALMART SHARED', '1953 west brown street',916523)]

d = defaultdict(list)

for name, address, code in lst:
    d[code].append({'cancmpname': name, 'canaddress': address})

Result

defaultdict(list,
            {916523: [{'canaddress': '601 12th Avenue Northeast',
                       'cancmpname': 'WALMART'},
                      {'canaddress': '1953 west brown street',
                       'cancmpname': 'WALMART SHARED'}]})

Explanation

  • Do not name variables after classes, eg use lst instead of list , d instead of dict .
  • For each item in lst , build a dictionary and append it with key equal to the code.

Benchmarking

lst = [('WALMART', '601 12th Avenue Northeast',916523), 
       ('WALMART SHARED', '1953 west brown street',916523)]

def jpp(lst):
    d = defaultdict(list)
    for name, address, code in lst:
        d[code].append({'cancmpname': name, 'canaddress': address})
    return d

def ajax(l):
    return {a:[dict(zip(['cancmpname', 'canaddress'], i[:-1])) for i in b] for a, b in itertools.groupby(l, key=lambda x:x[-1])}

lst = lst*1000

%timeit jpp(lst)    # 696 µs per loop
%timeit ajax(lst)   # 3.68 ms per loop

Here is a solution which does not use any library, although I think the defaultdict solution is cleanner:

li = [('WALMART', '601 12th Avenue Northeast',916523),
('WALMART SHARED', '1953 west brown street',916523)]

d = {}

for name, address, zipcode in li:
    d.setdefault(zipcode, []).append(dict(cancmpname=name, canaddress=address))

A few notes

  • Do not use list and dict to name your variables, you effectively overshadow the built-in types
  • If a key is not in the dictionary, setdefault will create the value (an empty list in this case) and assign to that key
  • If a key already exists in the dictionary, setdefault will do nothing
  • In both cases, setdefault will return the value for that key, which I took and append a new dictionary to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM