将元组列表转换为字典,一个键对应多个字典值

3

我的元组列表:

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

希望将元组列表转换为如下所示的字典:

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

            },
        ]
    }

我目前的代码:

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

这将列表转换为字典,并使用最新的值,而不是将两个结果附加为字典数组值。

我的代码结果:

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

            }

    }

使用 append() 将一个新的字典添加到列表中。 - Barmar
3个回答

5

您可以使用 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])}

输出:

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

就像阅读一行命令一样,优雅而熟练! - Xiang
@Xiang 谢谢!itertools + 列表推导式非常强大。 - Ajax1234

5
你可以使用 collections.defaultdict 实现 O(n) 级别的解决方案。
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})

结果

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

解释

  • 不要使用类名作为变量名,例如使用lst而不是list,使用d而不是dict
  • 对于lst中的每个项目,构建一个字典并将其附加到键等于代码的键。

基准测试

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

3

这里有一个解决方案,不使用任何库,虽然我认为defaultdict的解决方案更简洁:

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))

一些说明:
  • 不要使用 listdict 来命名变量,否则会影响内置类型
  • 如果字典中没有该键,则 setdefault 会创建值(在本例中为一个空列表)并分配给该键
  • 如果字典中已存在键,则 setdefault 不会执行任何操作
  • 在这两种情况下,setdefault 将返回该键的值,我将其取出并将一个新字典附加到其上。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接