从键列表和值列表列表中创建字典列表?

时间:2014-12-14 10:32:52

标签: python list dictionary

以下是将用于创建字典的键。

keys = ['a', 'b','c']

添加挑战的是列表中包含不同嵌套级别的值列表,这些列表需要展平,但前提是它只有一个项目。例如,[3,3,5]不应该被展平,因为它代表一个群组。

values = [
[[1],[1],[1]],
[[1],[0],1],
[2,0,[3,3,5]],
[1,[[1]],0]
]

我尝试了print dict(zip(key_list, cols)),但这似乎并没有产生预期的输出:

[{'a':1, 'b':1, 'c':1} , {'a':1, 'b':0, 'c':1}, {'a':2, 'b':0, 'c':[3,3,5]}]

5 个答案:

答案 0 :(得分:2)

根据您的输入和预期输出,您可以通过使用循环来克服单个嵌套挑战。 该程序可以写成

values = [
[[1],[1],[1]],
[[1],[0],1],
[2,0,[3,3,5]],
[1,[[1]],0]
]
keys = ['a','b','c']
l = []
for i in values:
    d = dict()
    for j in range(3):
        ele = i[j]
        while isinstance(ele,list) and len(ele) == 1:
            ele = ele[0]
        else:
            d[keys[j]] = ele
    l.append(d)     
print (l)   

输出

[{'a': 1, 'b': 1, 'c': 1}, {'a': 1, 'b': 0, 'c': 1}, {'a': 2, 'b': 0, 'c': [3, 3, 5]}, {'a': 1, 'b': 1, 'c': 0}]

正如所料。 (但是当字典被散列时,顺序会有所不同)

注意 - 我使用 SHORT CIRCUIT EVALUATION 来防止使用多个条件语句

答案 1 :(得分:1)

由于深度嵌套,您需要递归或迭代地展平单个元素列表。我根据您的规范使用get_flat来完成它。

#!/usr/bin/env python

# flatten single element lists recursively.
# using a while loop is probably better
def get_flat(elem):
    if isinstance(elem, list):
        if len(elem) > 1:
            return elem
        else:
            return get_flat(elem[0])
    return elem

values = [
    [[1],[1],[1]],
    [[1],[0],1],
    [2,0,[3,3,5]],
    [1,[[1]],0]
]
keys = ['a','b', 'c']

# zip keys and values for each flat column (uses get_flat to flatten)
# and convert to dict
print map(dict, map(lambda col: zip(keys, map(get_flat, col)), values))

输出:

[{'a': 1, 'c': 1, 'b': 1}, {'a': 1, 'c': 1, 'b': 0}, {'a': 2, 'c': [3, 3, 5], 'b': 0}, {'a': 1, 'c': 0, 'b': 1}]

答案 2 :(得分:0)

首先你需要平衡你的值,你可以使用以下递归函数来完成:

>>> def flat(l):
...  if not any(isinstance(i,list) and len(i)==1 for v in l for i in v):
...   return l
...  else :
...   return flat([[i[0] if isinstance(i,list) and len(i)==1 else i for i in v] for v in l])
... 

>>> flat(values)
[[1, 1, 1], [1, 0, 1], [2, 0, [3, 3, 5]], [1, 1, 0]]

然后使用以下列表理解:

>>> [dict(zip(keys,l)) for l in flat(values)]
[{'a': 1, 'c': 1, 'b': 1}, {'a': 1, 'c': 1, 'b': 0}, {'a': 2, 'c': [3, 3, 5], 'b': 0}, {'a': 1, 'c': 0, 'b': 1}]

但是这给了你一个包含4个项目的词典列表,你想要3,意味着你想要[1, 0, 1][1, 1, 0]的一个词典,因此你需要删除其中一个你能做到的排序它们和列表理解:

>>> p=[sorted(i) for i in flat(values)]
>>> [j for i,j in enumerate(p) if p[i+1:].count(j)<1]
[[1, 1, 1], [0, 2, [3, 3, 5]], [0, 1, 1]]

>>> [dict(zip(keys,l)) for l in last_l]
[{'a': 1, 'c': 1, 'b': 1}, {'a': 0, 'c': [3, 3, 5], 'b': 2}, {'a': 0, 'c': 1, 'b': 1}]

答案 3 :(得分:0)

你可以写一个递归函数,它可以根据你拥有的嵌套列表的级别来展平你的列表。

与您的情况类似,[[1]]

的最高嵌套列表级别为2
def get_values(values,count):
    for i in range(count):
        count = count - 1
        values = [[each[0] if isinstance(each, list) and len(each) ==1 else each for each in val] for val in values]
        return get_values(values,count)
    else:
        return values

keys = ['a', 'b','c']
values = [
        [[1],[1],[1]],
        [[1],[0],1],
        [2,0,[3,3,5]],
        [1,[[1]],0]
        ]       
count = max([str(each).count('[') for row in values for each in row if isinstance(each, list)])
# count = 2
print [dict(zip(keys, each)) for each in get_values(values, count)]     

结果:

[{'a': 1, 'c': 1, 'b': 1}, {'a': 1, 'c': 1, 'b': 0}, 
{'a': 2, 'c': [3, 3, 5], 'b': 0}, {'a': 1, 'c': 0, 'b': 1}]

如果最大嵌套级别为3,则只需将3作为参数传递给递归函数。

例如,此处值为元素[[[1]]]的最大嵌套级别为3,因此我们只需传递3作为get_values函数的计数参数值:

keys = ['a', 'b','c']
values = [
        [[1],[1],[1]],
        [[1],[0],1],
        [2,0,[3,3,5]],
        [1,[[[1]]],0]
        ]       

count = max([str(each).count('[') for row in values for each in row if isinstance(each, list)])
# count = 3
print [dict(zip(keys, each)) for each in get_values(values, count)]     

结果:

[{'a': 1, 'c': 1, 'b': 1}, {'a': 1, 'c': 1, 'b': 0}, 
{'a': 2, 'c': [3, 3, 5], 'b': 0}, {'a': 1, 'c': 0, 'b': 1}]

答案 4 :(得分:-1)

我假设你的最后一句话意味着    [{'a':1,'b':1,'c':1},{'a':1,'b':0,'c':1},{'a':2,'b ':0,'c':[3,3,5]}] 是你的预期产量。

然后

keys = ['a', 'b', 'c']
values = [
[[1],[1],[1]],
[[1],[0],1],
[2,0,[3,3,5]],
[1,[[1]],0]
]

print [dict(zip(keys, entry)) for entry in values]

是您想要的结果。

[{'a': [1], 'b': [1], 'c': [1]}, {'a': [1], 'b': [0], 'c': 1}, {'a': 2, 'b': 0, 'c': [3, 3, 5]}, {'a': 1, 'b': [[1]], 'c': 0}]

你的问题是zip(键,值)将构成值的每个列表视为键指向的值。所以你得到了

{'a': [[1], [1], [1]], 'c': [2, 0, [3, 3, 5]], 'b': [[1], [0], 1]}