Python 将嵌套元组列表转换为字典

Python convert a list of nested tuples into a dict

好的,所以我正在尝试编写一个 Python 函数,将此处的第一行(嵌套元组列表)转换为第二行,一个扁平化的字典:

[('Ka',0.6), ('La', 0.6), (('Ma', 0.7), ('Na', 0.8), ('Oa', 0.9))]   
{'La': 0.6, 'Ma': 0.7, 'Ka': 0.6, 'Na': 0.8, 'Oa': 0.9}

有点复杂的是列表中的外部元组是不同对象的成员,函数的参数是这些对象的列表。希望下面的代码解释了这一点。

现在我实际上已经设法拼凑出这个问题的解决方案,但它太可怕了,我不得不问如何以更 pythonic / 更少混淆的方式做到这一点:

def theFunction(args):
    # Please don't ask me how this works. It just does.
    flatten = lambda *n: (e for a in n for e in (flatten(*a) if
        isinstance(a, (tuple, list)) else (a,)))
    return dict(list(zip(*([iter(list(flatten(list(l.sn for l in args))))]*2))))

class le:
    def __init__(self,n):
        self.sn = (n,0.6)

class lf:
    def __init__(self,n,m,o):
        self.sn = (n,0.7), (m,0.8), (o, 0.9)

l1 = le("Ka")
l2 = le("La")
l3 = lf("Ma","Na","Oa")
theList = [l1,l2,l3]
print([l.sn for l in theList])
print(theFunction(theList))

两个打印语句将问题顶部的两行作为输出。

您能否更改 le 的定义,使 self.sn 成为元组的元组,就像 lf 中那样?如果是这样,这很容易:

class le:
    def __init__(self, n):
        self.sn = (n, 0.6), 
        #                 ^ make self.sn a tuple of tuples in all cases

class lf:
    def __init__(self, n, m, o):
        self.sn = (n, 0.7), (m, 0.8), (o, 0.9)

l1 = le("Ka")
l2 = le("La")
l3 = lf("Ma","Na","Oa")
theList = [l1, l2, l3]
result = dict([tup for thing in theList for tup in thing.sn])
# result == {'Na': 0.8, 'Ka': 0.6, 'Ma': 0.7, 'Oa': 0.9, 'La': 0.6}

此外,也许考虑不要在短变量名中如此随意地使用小写字母 "L"s,因为在大多数字体中阅读起来很费力。

您可以轻松地编写一个递归展平器,但是对于元组的双元素元组,这不会像预期的那样表现,例如(('tuple','one'), ('tuple','two'))

def recurse_flatten(seq):
    for el in seq:
        if isinstance(el, tuple) and len(el)==2:
            yield el
        else:
            yield from recurse_flatten(el)

>>> dict(recurse_flatten([('Ka',0.6), ('La', 0.6), (('Ma', 0.7), ('Na', 0.8), ('Oa', 0.9))]))
{'Ma': 0.7, 'Na': 0.8, 'La': 0.6, 'Ka': 0.6, 'Oa': 0.9}

您可以通过改进您的 yield 条件来取得更大的成功:

def recurse_flatten(seq):
    for el in seq:
        if isinstance(el, tuple) and len(el)==2:
            one,two = el
            if isinstance(one, str) and isinstance(two,float):
                yield el
                continue
        yield from recurse_flatten(el)