Actualización de valores de diccionario usando zip () en python

Actualización de valores de diccionario usando zip () en python

Tengo 4 listas de flotantes que extraje de un archivo JSON. Tengo que modificar los valores en estas 4 listas simultáneamente, dependiendo de la primera lista. Estoy usando zip() para iterar sobre las 4 listas, pero no puedo actualizar los valores en el diccionario original que representa el JSON.

Necesito verificar el signo de un elemento en la primera lista, si es negativo, todos los valores en las 4 listas que tienen el mismo índice que ese elemento deben ponerse a cero. El siguiente fragmento de código contiene algunos datos de muestra:

{
   "channels": [
      {
         "name": "TTZAR1e", 
         "samples": [
            {
               "data": [0.0996781, 0.0177724, -0.00566106],
               "modifiers": [
                  {"data": [0.084338, 0.0103356, 0.010294], "type": "staterror"}, 
                  {"data": {"hi_data": [0.0996781, 0.0177724, -0.00566106], "lo_data": [0.0996781, 0.0177724, -0.00566106]}, "type": "histosys"} 
                ], 
               "name": "conv"
            }
         ]
      }            
  ]
} 

Y esto es lo que he probado hasta ahora:

import json 
file = open("test1.json", 'r')
json_data = json.load(file)

for key, value in json_data.items():
    for i in value:
        for samp in i.get('samples'):
            for mod in samp.get('modifiers'):
                hi_list=[]
                lo_list=[]
                if(mod.get('type') == 'staterror'):
                    stat_list = mod.get('data')
                if(mod.get('type') == 'histosys'):
                    hi_list = mod.get('data').get('hi_data')
                    lo_list = mod.get('data').get('lo_data')
                for val, val2, val3, val4 in zip(samp.get('data'), hi_list, lo_list, stat_list):
                    if (val<0):
                        val,val2,val3,val4  = 0,0,0,0

Cuando imprimo el JSON, sigo obteniendo los valores negativos originales. El resultado final en el que estoy trabajando es algo como lo siguiente:

{
   "channels": [
      {
         "name": "TTZAR1e", 
         "samples": [
            {
               "data": [0.0996781, 0.0177724, 0],
               "modifiers": [
                  {"data": [0.084338, 0.0103356, 0],"type": "staterror"}, 
                  {"data": {"hi_data": [0.0996781, 0.0177724, 0], "lo_data": [0.0996781, 0.0177724, 0]}, "type": "histosys"} 
                ], 
               "name": "conv"
            }
         ]
      }            
  ]
} 

Me gustaría saber cómo actualizar los valores en el propio diccionario. ¿Hay alguna manera de implementar esto aquí?

Mostrar la mejor respuesta

Creo que tu bucle es el mejor camino a seguir.

Gracias @ U12-Forward :) Sin embargo, no puedo propagar los cambios en los valores dictados... Estoy seguro de que me estoy perdiendo un paso importante aquí.

zip() crea una lista de tuplas. Estas tuplas no comparten ninguna memoria con las listas originales, lo que significa que no tiene forma de mutar las entradas a zip() usando lo que devuelve.

Debe almacenar referencias a las listas que desea modificar y luego modificarlas en el lugar. (Notaré que debería considerar seriamente simplificar este código, ya que la gran profundidad de anidamiento hace que este código sea difícil de leer y depurar). Aquí hay un fragmento de código que hace eso:

for key, value in json_data.items():
    for i in value:
        for samp in i.get('samples'):
            lists_to_modify = [samp.get('data')]
            for mod in samp.get('modifiers'):
                if(mod.get('type') == 'staterror'):
                    lists_to_modify.append(mod.get('data'))
                if(mod.get('type') == 'histosys'):
                    lists_to_modify.append(mod.get('data').get('hi_data'))
                    lists_to_modify.append(mod.get('data').get('lo_data'))
            for data_index in range(len(samp.get('data'))):
                if samp.get('data')[data_index] < 0:
                    for list_to_modify in lists_to_modify:
                        list_to_modify[data_index] = 0

Muchas gracias @BrokenBenchmark por la explicación, funciona :)) Al simplificar, ¿te refieres a los múltiples bucles "for"?

Sí. Los datos JSON en sí mismos contienen una gran cantidad de anidamiento, por lo que puedo ver por qué estos bucles pueden parecer necesarios, pero necesitará realizar un seguimiento de muchas variables diferentes a la vez. Por ejemplo, tuve que usar data_index en lugar de i en el bucle inferior for, ya que i se usó en un bucle externo. El uso de nombres descriptivos y la reducción del anidamiento ayudan a la legibilidad y facilitan que usted y otros identifiquen cualquier problema que pueda surgir con su código.

Sí, de hecho, el propio json tiene muchos anidamientos, que no se pueden cambiar, y conducen a estos bucles for. Me aseguraré de agregar las descripciones a los bucles anidados para que sea más legible, ¡gracias nuevamente por la solución y los consejos!

@Manlai y @BrokenBenchmark Tengo una pregunta de seguimiento rápida para actualizar el archivo json. Estoy intentando lo siguiente para producir un nuevo archivo json con los cambios anteriores: with open("test1.json", 'r') as file: json_data = json.load(file) (the above modifications) with open("new.json",'w') as file1: file1.write(json.dumps(json_data,indent=3)) Pero en mi nuevo archivo json, los valores se imprimen verticalmente en una nueva línea, en lugar del formato en el json original. ¿Hay alguna forma en que se pueda solucionar este problema? Gracias !