0

I have the following .json file, which have some lists like values in some elements:

{
  "paciente": [
    {
      "id": 1234,
      "nombre": "Pablo",
      "sesion": [
        {
          "id": 12345,
          "juego": [
            {
              "nombre": "bonzo",
              "nivel": [
                {
                  "id": 1234,
                  "nombre": "caida libre"
                }
              ],
              "___léeme___": "El array 'iteraciones' contiene las vitorias o derrotas con el tiempo en segundos de cada iteración",
              "iteraciones": [
                {
                  "victoria": true,
                  "tiempo": 120
                },
                {
                  "victoria": false,
                  "tiempo": 232
                }
              ]
            }
          ],
          "segmento": [
            {
              "id": 12345,
              "nombre": "Hombro",
              "movimiento": [
                {
                  "id": 12,
                  "nombre": "flexion",
                  "metricas": [
                    {
                      "min": 12,
                      "max": 34,
                      "media": 23,
                      "moda": 20
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "id": 156,
      "nombre": "Bernardo",
      "sesion": [
        {
          "id": 456,
          "juego": [
            {
              "nombre": "Rita",
              "nivel": [
                {
                  "id": 1,
                  "nombre": "NAVEGANDO"
                }
              ],
              "___léeme___": "El array 'iteraciones' contiene las vitorias o derrotas con el tiempo en segundos de cada iteración",
              "iteraciones": [
                {
                  "victoria": true,
                  "tiempo": 120
                },
                {
                  "victoria": false,
                  "tiempo": 232
                }
              ]
            }
          ],
          "segmento": [
            {
              "id": 12345,
              "nombre": "Escapula",
              "movimiento": [
                {
                  "id": 12,
                  "nombre": "Protracción",
                  "metricas": [
                    {
                      "min": 12,
                      "max": 34,
                      "media": 23,
                      "moda": 20
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

From my script, I want to go through it's different nested elements for get specific information

import json

with open('myfile.json') as data_file:
    data = json.loads(data_file.read())


    patient_id = data["paciente"][0]["id"]

    patient_name = data["paciente"][0]["nombre"]

    id_session = data["paciente"][0]["sesion"][0]["id"]

    game_session = data["paciente"][0]["sesion"][0]["juego"][0]["nombre"]

    level_game = data["paciente"][0]["sesion"][0]["juego"][0]["nivel"][0]["nombre"]

    iterations = data["paciente"][0]["sesion"][0]["juego"][0]["iteraciones"]

    iterations_victory = data["paciente"][0]["sesion"][0]["juego"][0]["iteraciones"][0]["victoria"]

    iterations_time = data["paciente"][0]["sesion"][0]["juego"][0]["iteraciones"][0]["tiempo"]

    iterations_victory1 = data["paciente"][0]["sesion"][0]["juego"][0]["iteraciones"][1]["victoria"]

    iterations_time1 = data["paciente"][0]["sesion"][0]["juego"][0]["iteraciones"][1]["tiempo"]

    segment = data["paciente"][0]["sesion"][0]["segmento"][0]["nombre"]

    movement = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["nombre"]

    #metrics = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["metricas"]

    metric_min = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["metricas"][0]["min"]

    metric_max = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["metricas"][0]["max"]

    metric_average = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["metricas"][0]["media"]

    metric_moda = data["paciente"][0]["sesion"][0]["segmento"][0]["movimiento"][0]["metricas"][0]["moda"]

    print(
        'Patient ID:', patient_id,'\n',
        'Patient Name:', patient_name, '\n',
        'Session:','\n',
        '  Id Session:',id_session,'\n',
        '  Game:', game_session, '\n',
        '  Level:', level_game, '\n',
        '  Iterations:', len(iterations),'\n',
        '    Victory:', iterations_victory, '\n',
        '    Time:', iterations_time, '\n',
        '    Victory:', iterations_victory1, '\n',
        '    Time:', iterations_time1, '\n',
        '  Affected Segment:', segment, '\n',
        '    Movement:', movement, '\n',
        '       Metrics:','\n',
        '          Minimum:', metric_min, '\n'
        '          Maximum:', metric_max, '\n'
        '          Average:', metric_average, '\n'
        '          Moda/Trend:', metric_moda, '\n'

        )

This is my output:

Patient ID: 1234
 Patient Name: Pablo
 Session:
   Id Session: 12345
   Game: bonzo
   Level: caida libre
   Iterations: 2
     Victory: True
     Time: 120
     Victory: False
     Time: 232
   Affected Segment: Hombro
     Movement: flexion
        Metrics:
           Minimum: 12
          Maximum: 34
          Average: 23
          Moda/Trend: 20

[Finished in 0.0s]

Is it possible to optimize this code? How to can I make this code more readable or short?

I would like especially when I will have query for more of one element (just in case of that exist) in the lists/arrays like as segment, movement, iterations, games, etc

Any orientation is welcome.

martineau
  • 119,623
  • 25
  • 170
  • 301
bgarcial
  • 2,915
  • 10
  • 56
  • 123
  • 1
    Optimize? Really no need, you can trim down your code if you assign `data["paciente"][0]["sesion"][0]["segmento"][0]` to a variable and access the consequent contents from there. Also, that *will* speed things up *a bit* because you reduce the number of times you access the dictionary (which is fast ergo why it's a small speed-up) – Dimitris Fasarakis Hilliard Sep 18 '16 at 06:31
  • 2
    This might be a better question for the Code Review StackExchange site. – mgarey Sep 18 '16 at 07:19
  • The purpose of your code is unclear. It assigns the entire contents a nicely formed nested data structure to a bunch of unconnected variables. That's not going to do you any good. You should change your approach instead of trying to "optimize" this doomed code. – Tomalak Sep 18 '16 at 07:24
  • @Tomalak It's true I am getting the entire content of `json` document, and is possible that I don't express my goal of a clear way. I want access to each value of each key specified in my variables for manipulate them and place them in anywhere, but my doubts appear when I go through some list elements and so... – bgarcial Sep 18 '16 at 07:57
  • 1
    Well you probably don't just want to print them. Usally it's easier if you describe what your final goal is. Elegant code depends on what you intend to do. – Tomalak Sep 18 '16 at 17:21

2 Answers2

1

Depending on what else your program is doing, it may or may not matter if you speed the code up. You should use the profile or cProfile module to find out where your script is spending its time and work on those.

Regardless, you could save some processing time by removing all the redundant indexing operations by using temporary variable to hold the result. You can think of this simple as the removal of common prefixes. It's relatively easy if you've got a good code editor.

Although it may not be shorter or more readable code, it likely will execute faster (although there is some overhead involved).

Here's what I'm describing:

import json

with open('myfile.json') as data_file:
    data = json.loads(data_file.read())

    patient0_data = data["paciente"][0]

    patient_id = patient0_data["id"]
    patient_name = patient0_data["nombre"]

    patient0_data_sesion0 = patient0_data["sesion"][0]

    id_session = patient0_data_sesion0["id"]

    patient0_data_sesion0_juego0 = patient0_data_sesion0["juego"][0]

    game_session = patient0_data_sesion0_juego0["nombre"]
    level_game = patient0_data_sesion0_juego0["nivel"][0]["nombre"]
    iterations = patient0_data_sesion0_juego0["iteraciones"]

    patient0_data_sesion0_juego0_iteraciones = patient0_data_sesion0_juego0["iteraciones"]

    iterations_victory = patient0_data_sesion0_juego0_iteraciones[0]["victoria"]
    iterations_time = patient0_data_sesion0_juego0_iteraciones[0]["tiempo"]
    iterations_victory1 = patient0_data_sesion0_juego0_iteraciones[1]["victoria"]
    iterations_time1 = patient0_data_sesion0_juego0_iteraciones[1]["tiempo"]

    patient0_data_sesion0_segmento0 = patient0_data_sesion0["segmento"][0]

    segment = patient0_data_sesion0_segmento0["nombre"]

    patient0_data_sesion0_segmento0_movimiento0 = (
                                    patient0_data_sesion0_segmento0["movimiento"][0])

    movement = patient0_data_sesion0_segmento0_movimiento0["nombre"]
    #metrics = patient0_data_sesion0_segmento0_movimiento0["metricas"]

    patient0_data_sesion0_segmento0_movimiento0_metricas0 = (
                        patient0_data_sesion0_segmento0["movimiento"][0]["metricas"][0])

    metric_min = patient0_data_sesion0_segmento0_movimiento0_metricas0["min"]
    metric_max = patient0_data_sesion0_segmento0_movimiento0_metricas0["max"]
    metric_average = patient0_data_sesion0_segmento0_movimiento0_metricas0["media"]
    metric_moda = patient0_data_sesion0_segmento0_movimiento0_metricas0["moda"]

    print(
        'Patient ID:', patient_id,'\n',
        'Patient Name:', patient_name, '\n',
        'Session:','\n',
        '  Id Session:',id_session,'\n',
        '  Game:', game_session, '\n',
        '  Level:', level_game, '\n',
        '  Iterations:', len(iterations),'\n',
        '    Victory:', iterations_victory, '\n',
        '    Time:', iterations_time, '\n',
        '    Victory:', iterations_victory1, '\n',
        '    Time:', iterations_time1, '\n',
        '  Affected Segment:', segment, '\n',
        '    Movement:', movement, '\n',
        '       Metrics:','\n',
        '          Minimum:', metric_min, '\n'
        '          Maximum:', metric_max, '\n'
        '          Average:', metric_average, '\n'
        '          Moda/Trend:', metric_moda, '\n'

        )
martineau
  • 119,623
  • 25
  • 170
  • 301
  • It's true, I can simplify my expressions or temporary variables like you tell me, although this approach include that I should create this auxiliar or temporary variables for each record in the json `0` .. `1` – bgarcial Sep 19 '16 at 02:55
  • 1
    I don't see how it would make the creation of auxiliary variables in the json necessary. Yes it creates a lot of temporary variables _in the running script_ (to simplify subsequent access to their contents), but that shouldn't affect the creation of json at all as far as I can imagine. – martineau Sep 19 '16 at 03:11
1

Note that you are omitting the second patient record in your data (Bernardo), and that you assume there are always exactly two iterations. This might not always be true.

When you look for speed, your code is close to the best you can get, but for the above reasons, you would probably do good to add some tests and loops to make sure you cover all data, and not more.

Here is a function you could use to print the data in your format, based on a template you pass it. The template lists all labels you want to use for the keys you want to print the values for. In order to avoid ambiguity, the template needs both the key and the parent key of the elements of interest.

As the function needs to visit the keys in order, OrderedDict is used instead of dict:

import json
from collections import OrderedDict

data = json.loads(data, object_pairs_hook=OrderedDict)

def pretty(template, item, parentName='', name='', indent=0):
    label = template.get(parentName + '/' + name)
    if label:
        label = '  ' * indent + label + ': '
        if isinstance(item, list):
            label += str(len(item))
        elif not isinstance(item, OrderedDict):
            label += str(item)
        print(label)
    if isinstance(item, list):
        for value in item:
            pretty(template, value, parentName + '[]', name, indent)
    elif isinstance(item, OrderedDict):
        for key, value in item.items():
            pretty(template, value, name, key, indent+1)


template = {
    "paciente/id": "Patient ID",
    "paciente/nombre": "Patient Name",
    "paciente/sesion": "Sessions",
    "sesion/id": "Id Session",
    "juego/nombre": "Game",
    "nivel/nombre": "Level",
    "juego/iteraciones": "Iterations",
    "iteraciones/victoria": "Victory",
    "iteraciones/tiempo": "Time",
    "segmento/nombre": "Affected Segment",
    "movimiento/nombre": "Movement",
    "movimiento/metricas": "Metrics",
    "metricas/min": "Minimum",
    "metricas/max": "Maximum",
    "metricas/media": "Average",
    "metricas/moda": "Moda/Trend"
}

pretty(template, data)

The output is:

    Patient ID: 1234
    Patient Name: Pablo
    Sessions: 1
      Id Session: 12345
        Game: bonzo
          Level: caida libre
        Iterations: 2
          Victory: True
          Time: 120
          Victory: False
          Time: 232
        Affected Segment: Hombro
          Movement: flexion
          Metrics: 1
            Minimum: 12
            Maximum: 34
            Average: 23
            Moda/Trend: 20
    Patient ID: 156
    Patient Name: Bernardo
    Sessions: 1
      Id Session: 456
        Game: Rita
          Level: NAVEGANDO
        Iterations: 2
          Victory: True
          Time: 120
          Victory: False
          Time: 232
        Affected Segment: Escapula
          Movement: Protracción
          Metrics: 1
            Minimum: 12
            Maximum: 34
            Average: 23
            Moda/Trend: 20
trincot
  • 317,000
  • 35
  • 244
  • 286
  • Hi @trincot. In first instance, thanks a lot for your approach and I bring my apologies because I think that you in the previous comment did refer to my name Bernardo and I don't note that was to the second patient record of `nombre` attribute with value of `Bernardo` I've misread your previous comment and I sorry have been reported with flag. My apologies please. – bgarcial Sep 19 '16 at 02:30
  • In addition, it's true, I was only querying about of record [0], your approach with the function is interesting in the sense that allow me go through whole document. Let me try and test your recommendations please and analyze. Thanks, very much. – bgarcial Sep 19 '16 at 02:32
  • Hi @trincot. Thanks for your orientations and support. Can you check this related question with the approach that you gave me? http://stackoverflow.com/questions/39856278/how-to-send-values-from-view-to-template-from-a-json-file Best Regards. – bgarcial Oct 04 '16 at 15:35
  • 1
    I had a look, but I don't know django, so I cannot help you with that. Maybe someone else will answer. – trincot Oct 04 '16 at 16:48
  • Is possible that my question can be hava orientation from a python perspective? This mean, I want retrieve or get the values of the json document with the pretty function ... – bgarcial Oct 04 '16 at 16:54
  • 1
    Maybe, but then maybe you can specify what the output is that you want to have for the example JSON you provided. – trincot Oct 04 '16 at 16:57
  • I've fix my question. Thanks – bgarcial Oct 10 '16 at 22:44