【问题标题】:Convert list of tuples to dictionary with multiple dict values for a key将元组列表转换为具有多个字典值的字典
【发布时间】:2018-04-04 00:50:08
【问题描述】:

我的元组列表:

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() 将新字典追加到列表中。

标签: python python-3.x dictionary


【解决方案1】:

你可以使用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 谢谢! itertools + 列表理解非常强大。
【解决方案2】:

您可以使用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 都会返回该键的值,我采用该值并将新字典附加到它。

    【讨论】:

      猜你喜欢
      • 2013-04-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-05
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 2021-07-01
      • 2010-09-20
      相关资源
      最近更新 更多