Python将嵌套元组列表转换为dict

时间:2015-01-30 23:41:00

标签: python list dictionary

好的,所以我正在尝试编写一个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))

两个印刷语句在问题的顶部产生两行作为输出。

2 个答案:

答案 0 :(得分:2)

您可以更改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,因为在大多数字体中读取它是一个半小时。

答案 1 :(得分:0)

你可以很容易地编写一个递归的flattener,但是对于元组的两元素元组,这不会像预期的那样表现,例如: (('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)