嵌套的命名元组的平列表到字典列表

问题描述 投票:1回答:2

样本

import collections

A = collections.namedtuple('A', 'a b c')
B = collections.namedtuple('B', 'x y z w')

L = [A(a='CODE1',  b=B(x=2, y='u', z='v', w='a'), c=10),
     A(a='CODE2',  b=B(x=4, y='h', z='r', w='b'), c=30)]

我有一个命名元组列表,我想将其展平,用B的值替换嵌套的命名元组b

我尝试:

[我首先尝试将两个namedtuple都转换为字典并合并它们,但是问题是在dict理解中删除了原始的b值,而且排序是错误的:

t = [{k: v for k, v in {**x.b._asdict(), **x._asdict()}.items() 
      if k != 'b'} for x in L]
print (t)

[{'x': 2, 'y': 'u', 'z': 'v', 'w': 'a', 'a': 'CODE1', 'c': 10}, 
 {'x': 4, 'y': 'h', 'z': 'r', 'w': 'b', 'a': 'CODE2', 'c': 30}]

另一种解决方案可以根据需要运行,但是我认为这有点复杂-我更喜欢列表理解解决方案:

t = []
for x in L:
    out = {}
    d = x._asdict()
    for k, v in d.items():
        if isinstance(v, tuple):
            d1 = v._asdict()
            for k1, v1 in d1.items():
                out[k1] = v1
        else:
            out[k] = v
    t.append(out)

print (t)

[{'a': 'CODE1', 'x': 2, 'y': 'u', 'z': 'v', 'w': 'a', 'c': 10}, 
 {'a': 'CODE2', 'x': 4, 'y': 'h', 'z': 'r', 'w': 'b', 'c': 30}]
python list dictionary flatten namedtuple
2个回答
1
投票

具有复杂的dict/list理解:

from itertools import chain

...
res = [dict(chain.from_iterable(
            list(v._asdict().items()) if isinstance(v, (A, B)) else [(k, v)]
            for k, v in nt._asdict().items())) for nt in L]
print(res)

输出:

[{'a': 'CODE1', 'c': 10, 'w': 'a', 'x': 2, 'y': 'u', 'z': 'v'},
 {'a': 'CODE2', 'c': 30, 'w': 'b', 'x': 4, 'y': 'h', 'z': 'r'}]

0
投票

据我所知,字典中没有排序。如果订购对您很重要,则可以考虑使用Collections包中的OrderedDict(请参见manual)。顺便说一句,似乎namedtuple建立在OrderedDicts之上...

关于您的问题,也许您可​​以创建其他类型的namedtuple来强制执行您的命令:

AB = collections.namedtuple('AB', 'a x y z w c')

然后您可以根据需要显式转码:

list(map( lambda l: AB(l.a, l.b.x, l.b.y, l.b.z, l.b.w, l.c) , L)) 

并且如果由于某种原因您不想显式地写入B的字段,则可以使用以下方法来实现自动化:

AB(L[0].a,*[v for v in L[0].b._asdict()],L[0].c)

这就是我现在所能看到的,希望能有所帮助。

© www.soinside.com 2019 - 2024. All rights reserved.