Получить список полей из списка объектов (dict), импортированных из json - PullRequest
0 голосов
/ 09 июля 2019

Из этого JSON:

{
  "obj": [
    {
      "int": 0
    },
    {
      "int": 1
    }
  ]
}

Я хотел бы получить список int свойства поля obj, чтобы я мог выполнить агрегацию в списке, например, принимая среднее значение int в obj, используя синтаксис Jinja2.

Я попытался использовать фильтр selectattr("int") в сочетании с фильтром sum, но я получил `неподдерживаемые типы операндов для +: 'int' и 'dict'.

Я использую Jinja2 с docxtpl для создания файла docx из шаблона.

import json
j = '{"obj": [{"int": 0},{"int": 1}]}'
context = json.loads(j)

from docxtpl import DocxTemplate
import jinja2

tpl = DocXtemplate('template.docx')
tpl.render(context, jinja_env)
tpl.save('out.docx')

Шаблон docx содержит одну строку:

{{obj|selectattr("int")|sum}}

Я хотел бы видеть 1 в файле doxc при получении суммы, как я пытался сделать чуть выше, я также хотел бы иметь возможность сделать среднее и в конечном итоге использовать его в других операциях.

РЕДАКТИРОВАТЬ: В качестве ответа на те, кто говорит, что я должен сделать это в Python:

Я занимаюсь разработкой инструмента для создания отчетов docx из базы данных и файла шаблона. Первая часть инструмента - это программа на C ++, которая генерирует данные json из базы данных. Вторая часть - это скрипт для генерации отчета в формате docx из шаблона с использованием Jinja2. Я бы предпочел, чтобы пользователь только связывался с шаблоном и не нуждался в изменении скрипта, также я хотел бы иметь некоторую модульность и иметь возможность вычислять агрегации по дереву json. Поскольку Jinja2 предоставляет sum в списке и других видах операций, я подумал, что это может добавить еще один уровень модульности без необходимости писать больше кода. На данный момент я уже добавил возможность для пользователя выполнять агрегацию S на дереве json и вставлять его в дерево узлов, но мое решение не является идеальным, и оно стоит за счет предоставления другого файла шаблона для генерации данных, и это делает инструмент более сложный.

Надеюсь, теперь стало понятнее, почему я не хочу делать это в сценарии.

Edit2: Несколько более сложный пример:

{
    "arr": [
        {
            "obj": [
                {
                    "name": 0
                },
                {
                    "name": 1
                }
            ]
        },
        {
            "obj": [
                {
                    "name": 0
                },
                {
                    "name": 1
                }
            ]
        }
    ]
}

Я хотел бы иметь возможность сделать что-то вроде:

{{arr|get_attr_list('obj')|get_attr_list('int')}}

Еще лучшим решением было бы сделать расширение списка непосредственно в Jinja2:

{{ [ y[int] for y in x[obj] for x in arr ] | sum }}

Ответы [ 3 ]

3 голосов
/ 09 июля 2019

Это абсолютно не то, что вы должны делать в Jinja. Это язык шаблонов для отображения вещей.

Вы должны сделать это в Python, где это простая однострочная строка:

sum(item["int"] for item in context["obj"])
0 голосов
/ 09 июля 2019

Полный ответ работает как на простом, так и немного более сложном примере:

Я могу предоставить фильтр, который возвращает список, чтобы составить его, я должен проверить, является ли поле интереса списком, если это так, я должен сгладить результат. Пограничный случай должен быть более определенным, но он работает:

def get_list(value, arg):
  if type(value) is dict:
    return value[arg]
  elif type(value) is list:
    if len(value) == 0:
        return []
    else:
      res = [ x[arg] for x in value ]
      if type(res[0]) is list:
        res = list(itertools.chain(*res))
      return res
  else:
    return value

Тогда эта работа, как и ожидалось:

первый пример

{{ obj|get_list("int")|sum }}

(вывод 1)

второй пример

{{ arr|get_list("obj")|get_list("int")|sum }}

(вывод 2)

0 голосов
/ 09 июля 2019

Здесь

d= {
  "obj": [
    {
      "int": 0
    },
    {
      "int": 1
    }
  ]
}
# create a list
lst = [e['int'] for e in d['obj']]
print(lst)
# now you can do stats on this list
import statistics
mean = statistics.mean(lst)
print(mean)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...