仅在定义值时才更新Python字典

时间:2018-01-22 22:48:15

标签: python dictionary data-structures

如果我运行以下代码:

import json

foo = [
    {
        "name": "Bob",
        "occupation": "",
        "standing": "good",
        "locations": ["California"],
        "meta": { "last_updated": "2018-01-15" }
    },
    {
        "name": "",
        "occupation": "Carpenter",
        "standing": "bad",
        "locations": ["Arizona"],
        "meta": { "last_updated": "2018-01-15", "email": "bob@domain.com" }
    },
]

output = {}
for i in foo:
    output.update(i)
print json.dumps(output)

最终输出是:

{
    "locations": [
        "Arizona"
    ],
    "meta": {
        "email": "bob@domain.com",
        "last_updated": "2018-01-15"
    },
    "name": "",
    "occupation": "Carpenter",
    "standing": "bad"
}

这很不错。但是,我试图找出如何将函数传递给更新方法,该方法基本上说:“只有在定义了值/非空时才更新。”因此,在第一次迭代时名称是“Bob”,并且在第二次迭代时名称仍然是Bob,因为名称基本上是未定义的。

最终输出如下:

{
    "locations": [
        "Arizona"
    ],
    "meta": {
        "email": "bob@domain.com",
        "last_updated": "2018-01-15"
    },
    "name": "Bob",
    "occupation": "Carpenter",
    "standing": "bad"
}

3 个答案:

答案 0 :(得分:3)

您可以使用以下内容过滤正在更新的新词典:

b = {'bla': '', 'b': 77, 'c': '9'}
new_b = { k: v for k,v in b.items() if v }

new_b将不再有bla作为元素。

所以,在你的情况下:

for i in foo:
    output.update({ k: v for k,v in i.items() if v })

答案 1 :(得分:1)

您可以利用所有数据类型的固有布尔值,检查密钥是否存在和/或不是空/默认值:

Promise

注意,虽然它的一个缺点是,如果存在键DOES,BUT被映射到数据类型的默认(布尔值false)值,它将被覆盖:

output = {}
for i in foo:
    for k, v in i.iteritems():
        if not output.get(k):
            output[k] = v

In [6]: output
Out[6]:
{'locations': ['California'],
 'meta': {'last_updated': '2018-01-15'},
 'name': 'Bob',
 'occupation': 'Carpenter',
 'standing': 'good'}

答案 2 :(得分:1)

您可以使用Assembly assembly = Assembly.GetExecutingAssembly(); Stream strXml = assembly.GetManifestResourceStream("App.Dir.File.xml")); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(strXml); 将所有值与相同的键配对。首先,代码在itertools.groupby中的每个字典上调用dict.items并展平结果,从而启用组:

foo

输出:

import itertools
foo = [
{
    "name": "Bob",
    "occupation": "",
    "standing": "good",
    "locations": ["California"],
    "meta": { "last_updated": "2018-01-15" }
},
{
    "name": "",
    "occupation": "Carpenter",
    "standing": "bad",
    "locations": ["Arizona"],
    "meta": { "last_updated": "2018-01-15", "email": "bob@domain.com" }
  },
]
new_data = [(a, map(lambda x:x[-1], list(b))) for a, b in itertools.groupby(sorted(itertools.chain(*map(lambda x:x.items(), foo)), key=lambda x:x[0]), key=lambda x:x[0])]
final_data = {a:filter(None, b)[-1] for a, b in new_data}