【问题标题】:Retrieving specific data from a .json file more efficiently?更有效地从 .json 文件中检索特定数据?
【发布时间】:2017-01-26 01:27:00
【问题描述】:

我有以下.json 文件,其中有一些列表,例如某些元素中的值:

{
  "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
                    }
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

从我的脚本中,我想通过它的不同嵌套元素来获取特定信息

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'

        )

这是我的输出:

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]

是否可以优化此代码? 如何使这段代码更具可读性或更短?

我特别想查询列表/数组中的多个元素(以防万一存在),例如段、移动、迭代、游戏等

欢迎任何方向。

【问题讨论】:

  • 优化?真的没必要,如果您将data["paciente"][0]["sesion"][0]["segmento"][0] 分配给一个变量并从那里访问后续内容,您可以缩减您的代码。此外,这加快速度一点,因为您减少了访问字典的次数(这是快速的,所以它是一个小的加速)
  • 这对于 Code Review StackExchange 站点来说可能是一个更好的问题。
  • 您的代码的用途尚不清楚。它将整个内容分配给一堆未连接的变量,形成一个很好的嵌套数据结构。这对你没有任何好处。你应该改变你的方法,而不是试图“优化”这个注定失败的代码。
  • @Tomalak 确实我得到了json 文档的全部内容,并且可能我没有明确表达我的目标。我想访问我的变量中指定的每个键的每个值以操纵它们并将它们放在任何地方,但是当我浏览一些列表元素时我的疑虑出现了......
  • 好吧,您可能不只是想打印它们。通常,如果您描述最终目标是什么,会更容易。优雅的代码取决于您打算做什么。

标签: python arrays json


【解决方案1】:

根据您的程序正在执行的其他操作,是否加快代码速度可能很重要,也可能无关紧要。您应该使用 profilecProfile 模块来找出您的脚本将时间花在哪里并在这些地方工作。

无论如何,您可以通过使用临时变量来保存结果来删除所有冗余索引操作,从而节省一些处理时间。您可以认为这很简单,就像删除了常用前缀。如果你有一个好的代码编辑器,这相对容易。

虽然它可能不是更短或更易读的代码,但它可能会执行得更快(尽管涉及一些开销)。

这就是我所描述的:

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'

        )

【讨论】:

  • 是的,我可以像你告诉我的那样简化我的表达式或临时变量,尽管这种方法包括我应该为 json 0 .. @987654325 中的每条记录创建这个辅助或临时变量@
  • 我看不出它如何使在 json 中创建辅助变量成为必要。是的,它在运行脚本中创建了很多临时变量(以简化对其内容的后续访问),但据我所知,这根本不会影响 json 的创建。跨度>
【解决方案2】:

请注意,您在数据中省略了第二条患者记录 (Bernardo),并且您假设总是恰好有两次迭代。这可能并不总是正确的。

当您寻求速度时,您的代码接近于您所能获得的最佳速度,但由于上述原因,您最好添加一些测试和循环以确保您涵盖所有数据,而不是更多。

这是一个函数,可用于根据您传递的模板以您的格式打印数据。该模板列出了您要用于要为其打印值的键的所有标签。为了避免歧义,模板需要感兴趣元素的键和父键。

由于函数需要按顺序访问键,所以用OrderedDict代替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)

输出是:

    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。首先,非常感谢您的方法,我深表歉意,因为我认为您在之前的评论中确实提到了我的名字 Bernardo,我没有注意到这是 nombre 属性值的第二个患者记录Bernardo 我误读了你之前的评论,很抱歉被举报了。我很抱歉。
  • 另外,确实,我只是在查询记录 [0],您使用该功能的方法很有趣,因为它可以让我浏览整个文档。请让我尝试测试您的建议并进行分析。非常感谢。
  • 嗨@trincot。感谢您的指导和支持。你能用你给我的方法检查这个相关的问题吗? stackoverflow.com/questions/39856278/… 最好的问候。
  • 我看过,但我不知道 django,所以我无法帮助你。也许其他人会回答。
  • 也许可以,但也许您可以为您提供的示例 JSON 指定您想要的输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多