【问题标题】:How to loop through values in JSON and assign to another dictionary如何遍历 JSON 中的值并分配给另一个字典
【发布时间】:2022-01-26 10:05:14
【问题描述】:

我正在开发一个 Python/Django 网络应用程序。我正在尝试将 JSON 解析为 python 字典,读取字典中的值,并在满足某些条件时将值分配给另一个字典。

JSON 的结构如下:

{content: {cars: [0, 1, 2]}, other_stuff: []}

每辆车都有多个属性:

0: {"make", "model", "power"...}

每个属性都有三个变量:

make: {"value": "Toyota", "unit": "", "user_edited": "false"} 

我正在尝试将 JSON 中的值分配给其他字典; car_0、car_1 和 car_2。在这种情况下,考虑到每辆车,JSON 响应在其他方面都是相同的,但是第一辆车的“品牌”更改为“日产”,然后我试图将 car_0 的品牌也更改为“日产”。我正在通过以下方式解析 JSON:

    local_cars = [car_0, car_1, car_2] # Dictionaries which are already initialized.

    print(local_cars[0] is local_cars[1]) # Prints: false
    print(local_cars[0]['make']['value']) # Prints: Toyota (yes)
    print(local_cars[1]['make']['value']) # Prints: Toyota (yes)
    print(local_cars[2]['make']['value']) # Prints: Toyota (yes)
    
    counter = 0
    
    if request.method == 'POST':
        payload = json.loads(request.body)
        if bool(payload):
            print(len(local_cars)) # Prints: 3
            print(counter, payload['cars'][0]['make']['value']) # Prints: Nissan (yes)
            print(counter, payload['cars'][1]['make']['value']) # Prints: Toyota (yes)
            print(counter, payload['cars'][2]['make']['value']) # Prints: Toyota (yes)
            print(counter, local_cars[0]['make']['value']) # Prints: Toyota (yes)
            print(counter, local_cars[1]['make']['value']) # Prints: Toyota (yes)
            print(counter, local_cars[2]['make']['value']) # Prints: Toyota (yes)
            for target_car in payload['cars']: # Loop through all three cars in payload
                print(local_cars[0] is local_cars[1]) # false
                for attr in target_car.items(): # Loop through all key:dict pairs of a single car
                    attribute_key = attr[0] # Key (eg. 'make')
                    vars_dict = attr[1] # Dictionary of variables ('value': 'xx', 'unit': 'yy', 'user_edited': 'zz')
                    if vars_dict['user_edited'] == 'true':
                        local_cars[counter][attribute_key]['user_edited'] = 'true'
                        local_cars[counter][attribute_key]['value'] = vars_dict['value']
                print(counter, local_cars[counter]['make']['value']) # Prints: 0, Toyota (yes), 1, Nissan (no!), 2, Nissan (no!)              
                counter = counter + 1

我不明白为什么其他汽车 local_cars[1] 和 local_cars[2] 在这个循环中无论如何都会受到影响。可以看出,由于某种原因,他们的“品牌”被更改为“日产”,即使请求正文中的“丰田”也是如此。这似乎发生在第一轮'for target_car in payload['cars']中。

放弃循环/计数器并专注于一辆车没有任何区别:

for target_car in payload['cars']: --> target_car = payload['cars'][0]: 
...
local_cars[0][attribute_key]['user_edited'] = 'true'
local_cars[0][attribute_key]['value'] = vars_dict['value'] 

我做错了什么?即使我更改了代码的唯一部分,这些字典中的任何值都被编辑为仅影响 local_cars[0],如何影响 car_1 和 car_2?

更新

收到了正确的答案。在最初发布的部分代码之前,我初始化了 car_0、car_1 和 car_2 字典。

我之前做的是:

default_car = model_to_dict(Car.objects.first())
    
    car_0 = {}
    car_1 = {}
    car_2 = {}
    
    attribute = {}
    
    i = 0
    for key, value in default_car.items():
        if i > 1:
            attribute[key] = {"value": value, "unit": units.get(key), "user_edited": "false"}
        i = i + 1
        
    car_0.update(attribute)
    car_1.update(attribute)
    car_2.update(attribute)
    
    local_cars = [car_0, car_1, car_2]
    ...

显然问题在于所有 car_x 都与属性字典有关联。我通过将 car_x 初始化编辑为以下内容解决了这个问题:

default_car = model_to_dict(Car.objects.first())
    
    car_0 = {}
    car_1 = {}
    car_2 = {}
    
    attribute_0 = {}
    attribute_1 = {}
    attribute_2 = {}
    
    i = 0
    for key, value in default_car.items():
        if i > 1:
            attribute_0[key] = {"value": value, "unit": units.get(key), "user_edited": "false"}
            attribute_1[key] = {"value": value, "unit": units.get(key), "user_edited": "false"}
            attribute_2[key] = {"value": value, "unit": units.get(key), "user_edited": "false"}
        i = i + 1
        
    car_0.update(attribute_0)
    car_1.update(attribute_1)
    car_2.update(attribute_2)
    
    local_cars = [car_0, car_1, car_2]
    ...

【问题讨论】:

  • 将此for target_car in payload['cars']: 更改为for counter, target_car in enumerate (payload['cars']):,现在您可以使用枚举计数器并删除您的计数器。
  • 这很有帮助,使我的代码更具可读性,但并不能解决实际问题。还是谢谢!

标签: python python-3.x django dictionary django-views


【解决方案1】:

我认为您可能没有复制car_0 等。不要忘记python 分配纯粹是名称绑定。

x = car_0
y = car_0
print( x['make']['value'] ) # 'Toyota'
print( y['make']['value'] ) # 'Toyota'
print( x is y ) # True. Both names refer to the same object
x['make']['value'] = 'foo'
print( y['make']['value'] ) # 'foo'

应该是y = car_0.copy() 甚至是y=car_0.deepcopy()

我没有完全遵循您的代码,但如果您仍然不确定,请进行一些 is 测试以找出哪些实体绑定到同一个对象(并且不应该)。

【讨论】:

  • 我用添加的 is-tests 更新了我的原始问题。我想不出除了 local_cars[x] 是 local_cars[y] 和有效载荷 [cars][x] 是有效载荷 [cars][y] 之外还应该测试什么。似乎没有任何东西绑定到同一个对象。
  • 其实你是对的。问题与绑定对象有关,但在代码的早期部分,我没有包含在原始问题中。我更新了我原来的问题,以便将来可能对其他人有所帮助。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
相关资源
最近更新 更多