【问题标题】:Python list of tuples to dict [duplicate]dict的Python元组列表[重复]
【发布时间】:2019-03-29 04:37:46
【问题描述】:

有一个python列表

[('schema1', 'table1', 'column_name1'), ('schema1', 'table1', 'column_name2'), ('schema1', 'table2', 'column_name3'), ('schema2', 'table3', 'column_name4')]

我需要将它转换成具有以下结构的python dict

schema1:
            table1:
                    (column_name1,
                    column_name2)
            table2:
                    (column_name3)
schema2:
            table3:
                    (column_name4)

有什么有效的转化方式吗?

【问题讨论】:

  • 发布一些代码,展示你到目前为止所做的尝试。

标签: python python-3.x list dictionary defaultdict


【解决方案1】:

不需要任何特殊的东西,简单的字典方法就可以了:

d = [('schema1', 'table1', 'column_name1'), 
     ('schema1', 'table1', 'column_name2'), 
     ('schema1', 'table2', 'column_name3'), 
     ('schema2', 'table3', 'column_name4')]

k = {}

for schema,table,column in d:
    p =  k.setdefault(schema,{})
    p2 = p.setdefault(table,[])
    p2.append(column)

print(k)

输出:

{'schema1': {'table2': ['column_name3'], 
             'table1': ['column_name1', 'column_name2']}, 
 'schema2': {'table3': ['column_name4']}}

虽然更有经验的人建议不要使用它,因为它比较慢。所以最好使用其他答案提供的 defaultdict-approach。

【讨论】:

  • importdefaultdict 有什么问题?它也可能会更高效
  • @Chris_Rands defaultdicts 没有任何问题 - 但其他 2 个答案已经使用了这些 - 并且不需要。至于性能 - 我不知道哪个会更快/更好。必须对此进行测试。
  • Re:Performance, setdefault 较慢,因为默认是始终创建的,即使密钥存在(即使在那种情况下不使用它)。在默认字典的情况下,它会更好。
【解决方案2】:

我会使用defaultdict 来执行此操作,它会生成defaultdict(list) 实例作为默认值。

演示

>>> from collections import defaultdict
>>> 
>>> d = defaultdict(lambda: defaultdict(list))
>>> data = [('schema1', 'table1', 'column_name1'), ('schema1', 'table1', 'column_name2'), ('schema1', 'table2', 'column_name3'), ('schema2', 'table3', 'column_name4')]
>>> 
>>> for k1, k2, v in data:
...:    d[k1][k2].append(v)
...:    
>>> d
>>> 
defaultdict(<function __main__.<lambda>()>,
            {'schema1': defaultdict(list,
                         {'table1': ['column_name1', 'column_name2'],
                          'table2': ['column_name3']}),
             'schema2': defaultdict(list, {'table3': ['column_name4']})})

要完全匹配您想要的输出(尽管我看不出太多原因),请从 dtuple 值构建一个常规字典。

>>> d = {k1:{k2:tuple(v2) for k2, v2 in v1.items()} for k1, v1 in d.items()}
>>> d
>>> 
{'schema1': {'table1': ('column_name1', 'column_name2'),
  'table2': ('column_name3',)},
 'schema2': {'table3': ('column_name4',)}}

说明

defaultdict 初始值设定项接受一个可调用对象(在此示例中使用匿名 lambda 函数)。每当缺少键时,都会调用该可调用对象并将返回值用作备用值。

线

d = defaultdict(lambda: defaultdict(list))

正在创建一个defaultdict,它会在缺少密钥时创建另一个defaultdict。第二个 defaultdict 在缺少键时创建list

>>> d = defaultdict(lambda: defaultdict(list))
>>> d['bogus']
>>> defaultdict(list, {})
>>> d['hokus']['pokus']
>>> []

【讨论】:

    【解决方案3】:
    l = [('schema1', 'table1', 'column_name1'), ('schema1', 'table1', 'column_name2'), 
     ('schema1', 'table2', 'column_name3'), ('schema2', 'table3', 'column_name4')]
    d = {}
    
    for s, t, c in l:
        d[s] = d.get(s, {})
        d[s][t] = d[s].get(t, tuple()) + (c,)
    print(d)
    

    输出:

    {'schema1': {'table1': ('column_name1', 'column_name2'), 
                 'table2': ('column_name3',)}, 
     'schema2': {'table3': ('column_name4',)}}
    

    【讨论】:

      【解决方案4】:

      当然。使用collections.defaultdict

      from collections import defaultdict
      
      dd = defaultdict(lambda: defaultdict(list))
      
      for schema, table, colname in L:
          dd[schema][table].append(colname)
      

      结果:

      defaultdict(<function __main__.<lambda>>,
                  {'schema1': defaultdict(list,
                               {'table1': ['column_name1', 'column_name2'],
                                'table2': ['column_name3']}),
                   'schema2': defaultdict(list, {'table3': ['column_name4']})})
      

      【讨论】:

      • 这个比较优雅,我之前没用过这个特定的模式
      • @Chris_Rands,我觉得讽刺:)
      • 不,我不认为@Chris_Rands 知道这是重复的 ;-)
      猜你喜欢
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 2018-06-28
      • 2012-03-16
      • 2017-11-28
      • 2013-07-21
      • 1970-01-01
      • 2013-03-16
      相关资源
      最近更新 更多