【问题标题】:Counting occurence in nested JSON object计数嵌套 JSON 对象中的出现次数
【发布时间】:2021-08-09 16:34:54
【问题描述】:

给出如下五个列表:

make = ['ford', 'fiat', 'nissan', 'suzuki', 'dacia']
model = ['x', 'y', 'z']
version = ['A', 'B', 'C']
type = ['sedan', 'coupe', 'van', 'kombi']
infos = ['steering wheel problems', 'gearbox problems', 'broken engine', 'throttle problems', None]

还有 JSON 对象:

data = [
            {
                'id': 1,
                'make': 'ford',
                'model': 'x',
                'version': 'A',
                'type': 'sedan',
                'infos': [
                            {
                                "id": 999,
                                "name": 'steering wheel problems'
                            },
                            {
                                "id": 99,
                                "name": 'broken engine'
                            }
                ],
                'owner':
                            {
                                "id": 999,
                                "name": 'alice'
                            },
                "type":
                            {
                                "value": 987,
                                "id": 129,
                                "name": 'A',
                                "type": 'zaz'
                            }
            },
            ...
    ]

我需要迭代并创建 JSON 对象,其中包含具有此类列表中所有可能的项目组合的字段以及它们在对象 data 中出现的次数,这意味着具有特定品牌、型号、版本、类型和特定信息的汽车(不仅一个信息项目,而且可以是多个甚至整个信息列表)是一定数量的 - 假设有 2 辆这样的汽车。我期待这样的事情:

total = [
            {
                'make': 'ford',
                'model': 'x',
                'version': 'A',
                'type': 'sedan',
                'infos': [
                        {
                        'inf': 'steering wheel problems'
                        }
                ],
                'occurence': 0
            },
            ...
            {
                {
                'make': 'dacia',
                'model': 'z',
                'version': 'C',
                'type': 'kombi',
                'infos': [
                        {
                        'inf': 'steering wheel problems'
                        },
                        {
                        'inf': 'gearbox problems'
                        },
                        {
                        'inf': 'broken engine'
                        },
                        {
                        'inf': 'throttle problems'
                        }                        
                ],
                'occurence': 1
            }
         ]

我的尝试看起来像:

for i in infos:
        for j in make:
            for k in model:
                for m in version:
                    for n in type:
                        s = sum([1 for p in data if (data['infos'] == i and data['make'] == j and data['model'] == k and data['version'] == m and data['type'] == n))
                        total.append({'infos': i, 'make': j, 'model': k, 'version': m, 'type': n, 'occurence': s})
return total

但我特别坚持迭代infos。在这样的问题中如何编写正确的代码?

【问题讨论】:

  • 你坚持什么?你到底有什么问题?
  • “迭代信息”是什么意思?更重要的是,你到底坚持什么?运行代码时会发生什么?你想让它做什么呢?
  • 这是一个常见错误。我建议您在谷歌上搜索确切的消息,看看其他人已经提出了哪些解决方案。

标签: python json loops for-loop


【解决方案1】:

从您的问题来看,您似乎想要制作一个包含品牌、型号、类型和版本的所有组合以及所有信息组合作为单独字典条目的字典。您可以使用itertools中的组合和产品来制作字典,然后您可以遍历所有数据条目以检查它是否在字典中,然后计算它。如果您不想要数据中没有的组合,您可以使用计数器。

from itertools import combinations, product

info_combos = [combo for n in range(1, len(infos)+1) for combo in combinations(infos, n)]

total = {(ma, mo, v, t, tuple(i)): 0 for ma, mo, v, t, i in product(make, model, version, types, info_combos)}

for car in data:
    if all([car['make'] in make, 
            car['model'] in model, 
            car['type'] in types, 
            car['version'] in version]):
        # assuming infos in data are ordered:
        key = tuple([car['make'],
                     car['model'], 
                     car['version'], 
                     car['type'], 
                     tuple([i['name'] for i in car['infos']])])
        total[key] += 1

这会很慢,因为您的字典或计数器会随着品牌和模型中的更多条目而呈指数级增长,并且在您循环所有内容时使用大型数据集。

【讨论】:

  • 使用这个我遇到了:回溯(最近一次调用最后一次):文件“C:\Users\martin\Desktop\proj\proj.py”,第 219 行,在 中ma, mo, v, t, i in product(make, model, version, types, info_combos)} File "C:\Users\martin\Desktop\proj\proj.py", line 219, in for ma , mo, v, t, i in product(make, model, version, types, info_combos)} TypeError: unhashable type: 'dict'
  • 糟糕,抱歉。我忘记将这些更改为可散列对象,因为不能将字典作为键。您必须将键设为元组,而不是字典。
  • 发生另一个错误:文件“C:\Users\martin\Desktop\proj\proj.py”,第 228 行,在 total[key] += 1 KeyError: ('ford' , 'x', 'A', ('方向盘问题', '发动机坏了'))
  • 好像在做没有车型的钥匙;您可能遇到的一个问题是命名一个变量“类型”,因为这是一个内置名称,请使用不同的名称(我在我的中使用了“类型”。确保为字典创建键和创建每辆车的钥匙都是一样的,可能是你在将汽车钥匙放入字典时缺少添加类型。
  • 检查您的数据集在同一级别上没有两个键作为“类型”,看起来可能。它在我的机器上计算它们。
【解决方案2】:

如果你猜你的意思是你的测试data['infos'] == i 永远不会被评估为True。 在这里,您可能想要检查您的字典的infos 字段中是否必须有一个项目x,例如x['name'] == i。 如果这是您的问题,您可以将 sum 替换为:

s = sum(
   1 for p in data
   if any(x['name'] == i for x in p['infos'])   # test replaced here
      and p['make'] == j
      and p['model'] == k
      and p['version'] == m
      and p['type'] == n
)

请注意,您的解决方案将会非常缓慢,因为您需要遍历整个列表以查找每个可能的元组 (name, make, model, version, type)

【讨论】:

    猜你喜欢
    • 2022-01-24
    • 1970-01-01
    • 2021-09-21
    • 2021-09-07
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    相关资源
    最近更新 更多