【问题标题】:remove redundant key value from json array python从json数组python中删除冗余键值
【发布时间】:2021-01-22 11:22:25
【问题描述】:

我有一个json文件包含一个对象数组,文件里面的数据是这样的:

[
 {‘name’: ‘A’,
 ‘address’: ‘some address related to A’,
 ‘details’: ‘some details related to A’},
 {‘name’: ‘B’,
 ‘address’: ‘some address related to A’,
 ‘details’: ‘some details related to B’},
 {‘name’: ‘C’,
 ‘address’: ‘some address related to A’,
 ‘details’: ‘some details related to C’}
]

我想删除多余的键值,所以输出应该是这样的:

  [
   {‘name’: ‘A’,
   ‘address’: ‘some address related to A’,
   ‘details’: ‘some details related to A’},
   {‘name’: ‘B’,
   ‘details’: ‘some details related to B’},
   {‘name’: ‘C’,
   ‘details’: ‘some details related to C’}
  ]

所以,我试过这段代码,在link

import json

with open(‘./myfile.json’) as fp:
    data= fp.read()
  
unique = []
for n in data:
    if all(unique_data["address"] != data for unique_data["address"] in unique):
        unique.append(n)

#print(unique)   
with open(“./cleanedRedundancy.json”, ‘w’) as f:
     f.write(unique)

但它给了我这个错误:

TypeError: string indices must be integers

【问题讨论】:

  • for n in data 实际上会遍历文本data 的每个符号,因此每个迭代n 是文本的一个符号。那是你真正想要的吗?
  • 你必须解析 JSON。见How to parse JSON in Python?
  • 另外for unique_data["address"] in unique 应该真的是for unique_data in unique
  • @Arty,感谢您的回复,但请您再澄清一下,我并没有真正明白您所说的!
  • @n_dev 你能更详细地描述删除冗余条目的算法吗?然后我们可以创建一个工作代码来实现这样的算法。

标签: python arrays json


【解决方案1】:

我做了有/没有文件支持的解决方案,默认情况下,你的情况下支持文件在我的脚本中将use_files = False更改为use_files = True

我希望您要删除具有相同 (key, value) 对的重复项。

Try it online!

import json

use_files = False
# Only duplicates with next keys will be deleted
only_keys = {'address', 'complex'}

if not use_files:
    fdata = """
    [
     {
       "name": "A",
       "address": "some address related to A",
       "details": "some details related to A"
     },
     {
       "name": "B",
       "address": "some address related to A",
       "details": "some details related to B",
       "complex": ["x", {"y": "z", "p": "q"}],
       "dont_remove": "test"
     },
     {
       "name": "C",
       "address": "some address related to A",
       "details": "some details related to C",
       "complex": ["x", {"p": "q", "y": "z"}],
       "dont_remove": "test"
     }
    ]
    """

if use_files:
    with open("./myfile.json", 'r', encoding = 'utf-8') as fp:
        data = fp.read()
else:
    data = fdata

entries = json.loads(data)

unique = set()
for e in entries:
    for k, v in list(e.items()):
        if k not in only_keys:
            continue
        v = json.dumps(v, sort_keys = True)
        if (k, v) in unique:
            del e[k]
        else:
            unique.add((k, v))

if use_files:
    with open("./cleanedRedundancy.json", "w", encoding = 'utf-8') as f:
        f.write(json.dumps(entries, indent = 4, ensure_ascii = False))
else:
    print(json.dumps(entries, indent = 4, ensure_ascii = False))

输出:

[
    {
        "name": "A",
        "address": "some address related to A",
        "details": "some details related to A"
    },
    {
        "name": "B",
        "details": "some details related to B",
        "complex": [
            "x",
            {
                "y": "z",
                "p": "q"
            }
        ],
        "dont_remove": "test"
    },
    {
        "name": "C",
        "details": "some details related to C",
        "dont_remove": "test"
    }
]

【讨论】:

  • 我建议做一个小改动以避免在迭代时修改条目。我知道您创建了子条目的副本,但通常我们只会创建一个新的清理副本?
  • @KennyOstrom 为什么?我读入然后处理然后写出这个对象,只为给定的任务做一次转换。为什么我不能删除条目?我也做in list(entries.items()),这里list() 复制字典项,因此如果条目在飞行中发生变化,这个循环迭代不会有问题。
  • @n_dev 修正了我的答案!支持列表和任何复杂的值类型。通过将值转换为 json 字符串进行比较,使用了很好的技巧,对于相同的值,它们应该是相等的字符串。
  • @n_dev 另请参阅,在我的示例中,两个地方的嵌套字典具有不同的 "y""p" 键顺序,但如果它们的排序顺序相同,我仍然认为这些字典是相等的键,为此我使用了参数sort_keys = True,如果此类字典应被视为不相等,请替换为sort_keys = False
  • @n_dev 在脚本的开头刚刚添加了新的常量only_keys = ...,只放了需要删除的键。在您的情况下,只需执行 only_keys = {'address'} ,这将解决您上次请求的仅删除地址的任务。
猜你喜欢
  • 1970-01-01
  • 2013-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多