将.values()与字典列表一起使用?

时间:2018-11-12 16:14:51

标签: python json list-comprehension dictionary-comprehension

我正在比较两个不同API端点之间的json文件,以查看哪些json记录需要更新,哪些需要创建,哪些需要删除。因此,通过比较两个json文件,我想得到三个json文件,每个操作一个。

两个端点的json的结构如下(但它们对相同的值集使用不同的键;不同的问题):

{
    "records": [{
        "id": "id-value-here",
        "c": {
            "d": "eee"
        },
        "f": {
            "l": "last",
            "f": "first"
        },
        "g": ["100", "89", "9831", "09112", "800"]
    }, {

        …


    }]
}

因此json表示为字典列表(还有更多嵌套的列表和字典)。

如果另一个端点json(j2)中存在给定的json端点(j1)id值(“ id” :),则应将该记录添加到j_update。

到目前为止,我有类似的内容,但是我可以看到.values()不起作用,因为它试图对列表进行操作,而不是对所有列出的字典(?)进行操作:

j_update = {r for r in j1['records'] if r['id'] in 
j2.values()}

这不会返回错误,但是会使用测试json文件创建一个空集。

看起来像这样应该很简单,但是我想到代表json的列表中的字典会影响嵌套。我是否需要展平j2,还是有一种更简单的字典方法python必须做到这一点?

====编辑j1和j2 ==== 具有相同的结构,使用不同的键;玩具数据

j1

{
    "records": [{
        "field_5": 2329309841,
        "field_12": {
            "email": "cmix@etest.com"
        },
        "field_20": {
            "last": "Mixalona",
            "first": "Clara"
        },
        "field_28": ["9002329309999", "9002329309112"],
        "field_44": ["1002329309832"]
    }, {
        "field_5": 2329309831,
        "field_12": {
            "email": "mherbitz345@test.com"
        },
        "field_20": {
            "last": "Herbitz",
            "first": "Michael"
        },
        "field_28": ["9002329309831", "9002329309112", "8002329309999"],
        "field_44": ["1002329309832"]
    }, {
        "field_5": 2329309855,
        "field_12": {
            "email": "nkatamaran@test.com"
        },
        "field_20": {
            "first": "Noriss",
            "last": "Katamaran"
        },
        "field_28": ["9002329309111", "8002329309112"],
        "field_44": ["1002329309877"]
    }]
}

j2

{
    "records": [{
        "id": 2329309831,
        "email": {
            "email": "mherbitz345@test.com"
        },
        "name_primary": {
            "last": "Herbitz",
            "first": "Michael"
        },
        "assign": ["8003329309831", "8007329309789"],
        "hr_id": ["1002329309877"]
    }, {
        "id": 2329309884,
        "email": {
            "email": "yinleeshu@test.com"
        },
        "name_primary": {
            "last": "Lee Shu",
            "first": "Yin"
        },
        "assign": ["8002329309111", "9003329309831", "9002329309111", "8002329309999", "8002329309112"],
        "hr_id": ["1002329309832"]
    }, {
        "id": 23293098338,
        "email": {
            "email": "amlouis@test.com"
        },
        "name_primary": {
            "last": "Maxwell Louis",
            "first": "Albert"
        },
        "assign": ["8002329309111", "8007329309789", "9003329309831", "8002329309999", "8002329309112"],
        "hr_id": ["1002329309877"]
    }]
}

2 个答案:

答案 0 :(得分:0)

如果您阅读json,它将输出字典。您正在值列表中寻找特定键。

if 'records' in j2:
  r = j2['records'][0].get('id', []) # defaults if id does not exist

进行递归搜索比较好,但是我不知道您的数据如何组织起来以便快速提出解决方案。

要给出递归搜索的想法,请考虑以下示例

def resursiveSearch(dictionary, target):
    if target in dictionary:
        return dictionary[target]
    for key, value in dictionary.items():
        if isinstance(value, dict):
            target = resursiveSearch(value, target)
            if target:
                return target


a = {'test' : 'b', 'test1' : dict(x = dict(z = 3), y = 2)}

print(resursiveSearch(a, 'z'))

答案 1 :(得分:0)

您尝试过:

var newPostKey = firebaseref.child("user").push().set({name : messageText,prenom:prenomtxt ,email : txtmail}).key;

除了j_update = {r for r in j1['records'] if r['id'] in j2.values()} 问题之外,您还有:

r['id'/'field_5]

>>> list(j2.values()) [[{'id': 2329309831, ...}, ...]] 埋在列表和字典中,因此测试id始终返回False。

基本解决方案非常简单。 首先,创建一组r['id'] in j2.values() j2

id

然后,重建>>> present_in_j2 = set(record["id"] for record in j2["records"]) 的json结构,但不包含j1中不存在的j1 field_5

j2

它可以工作,但是由于>>> {"records":[record for record in j1["records"] if record["field_5"] in present_in_j2]} {'records': [{'field_5': 2329309831, 'field_12': {'email': 'mherbitz345@test.com'}, 'field_20': {'last': 'Herbitz', 'first': 'Michael'}, 'field_28': ['9002329309831', '9002329309112', '8002329309999'], 'field_44': ['1002329309832']}]} 怪异的键而不能令人满意。让我们尝试将j1转换为更友好的格式:

j1

此函数着重于字典键:如果转换表中存在键,则def map_keys(json_value, conversion_table): """Map the keys of a json value This is a recursive DFS""" def map_keys_aux(json_value): """Capture the conversion table""" if isinstance(json_value, list): return [map_keys_aux(v) for v in json_value] elif isinstance(json_value, dict): return {conversion_table.get(k, k):map_keys_aux(v) for k,v in json_value.items()} else: return json_value return map_keys_aux(json_value) conversion_table.get(k, k)

conversion_table[k]

现在,代码更简洁了,输出对于>>> j1toj2 = {"field_5":"id", "field_12":"email", "field_20":"name_primary", "field_28":"assign", "field_44":"hr_id"} >>> mapped_j1 = map_keys(j1, j1toj2) 可能更有用:

PUT