Вопрос или проблема
У меня есть два списка словарей, и я хотел бы пройтись по декартовому произведению как по одному. Как мне это сделать.
образцы данных:
environments: [
{title: outdoors, climate: variable},
{title: indoors, climate: steady}
],
colorscheme: [
{top: blue, bottom: red},
{top: pink, bottom: green}
]
желаемый результат:
item: [
{title: outdoors, climate: variable, top: blue, bottom: red},
{title: indoors, climate: steady, top: blue, bottom: red},
{title: outdoors, climate: variable, top: pink, bottom: green},
{title: indoors, climate: steady, top: pink, bottom: green}
]
Я пробовал выражение "{{ environments|product(colorscheme)|list }}"
, которое приближает меня к желаемому, но не совсем то, что я хочу.
Результаты выражения:
item: [
[
{title: outdoors, climate: variable},
{top: blue, bottom: red}
],
[
{title: indoors, climate: steady},
{top: blue, bottom: red}
],
[
{title: outdoors, climate: variable},
{top: pink, bottom: green}
],
[
{title: indoors, climate: steady},
{top: pink, bottom: green}
]
]
Вот один из способов, как это можно сделать. Не уверен, что это лучший способ.
- hosts: localhost
gather_facts: no
vars:
envs:
- title: outdoors
climate: variable
- title: indoors
climate: steady
colorscheme:
- top: blue
bottom: red
- top: pink
bottom: green
tasks:
- debug:
msg: >
[
{% for e in envs %}
{% for c in colorscheme %}
{{ e | combine (c) }},
{% endfor %}
{% endfor %}
]
# TASK [debug] **************************************************************************************************[3/1813$
# ok: [localhost] => {
# "msg": [
# {
# "bottom": "red",
# "climate": "variable",
# "title": "outdoors",
# "top": "blue"
# },
# {
# "bottom": "green",
# "climate": "variable",
# "title": "outdoors",
# "top": "pink"
# },
# {
# "bottom": "red",
# "climate": "steady",
# "title": "indoors",
# "top": "blue"
# },
# {
# "bottom": "green",
# "climate": "steady",
# "title": "indoors",
# "top": "pink"
# }
# ]
# }
#
Следующий (крайне уродливый) шаблон Jinja отобразит точно то, что просит автор:
item: [{% for c in colorscheme %}{% for e in environments %}
{% set noop = e.update(c) -%}{{ e }}{% if not loop.last %},{% endif %}{% endfor %}{% if not loop.last %},{% endif %}{% endfor %}
]
или, для удобочитаемости, вот тот же шаблон с добавленным пробелом:
item: [
{% for c in colorscheme %}
{% for e in environments %}
{% set noop = e.update(c) -%}
{{ e }}
{% if not loop.last %},{% endif %}
{% endfor %}
{% if not loop.last %},{% endif %}
{% endfor %}
]
Ответ или решение
Для выполнения задачи по созданию декартова произведения двух списков словарей в Ansible с использованием Jinja2, мы можем воспользоваться вложенными циклами. Цель заключается в объединении каждого элемента из одного списка со всеми элементами из другого списка. Давайте подробно рассмотрим, как этого можно достичь, опираясь на предоставленные данные.
Исходные данные
Рассмотрим два списка словарей: environments
и colorscheme
.
environments: [
{title: outdoors, climate: variable},
{title: indoors, climate: steady}
],
colorscheme: [
{top: blue, bottom: red},
{top: pink, bottom: green}
]
Ожидаемый результат
Вы хотите получить следующий результат:
item: [
{title: outdoors, climate: variable, top: blue, bottom: red},
{title: indoors, climate: steady, top: blue, bottom: red},
{title: outdoors, climate: variable, top: pink, bottom: green},
{title: indoors, climate: steady, top: pink, bottom: green}
]
Реализация в Ansible с использованием Jinja2
Для реализации этой задачи, мы воспользуемся двумя вложенными циклами в шаблоне Jinja2. Ниже представлен код, который выполняет поставленную задачу:
- hosts: localhost
gather_facts: no
vars:
environments:
- title: outdoors
climate: variable
- title: indoors
climate: steady
colorscheme:
- top: blue
bottom: red
- top: pink
bottom: green
tasks:
- name: Generate Cartesian product
debug:
msg: |
item: [
{% for c in colorscheme %}
{% for e in environments %}
{% set combined = e | combine(c) %}
{{ combined }}{% if not loop.last %},{% endif %}
{% endfor %}
{% if not loop.last %},{% endif %}
{% endfor %}
]
Пояснение кода
-
Входные данные: Мы определяем два списка переменных
environments
иcolorscheme
, содержащих словари с необходимыми свойствами. -
Отладка: Задача
debug
используется для отображения результата. Внутри задачи мы используем блокmsg
, чтобы создать строку с требуемой структурой. -
Вложенные циклы:
- Внешний цикл (
for c in colorscheme
) перебирает каждую цветовую схему. - Внутренний цикл (
for e in environments
) перебирает каждую среду. - Внутри внутреннего цикла мы используем фильтр
combine
для объединения текущих словарей из обоих списков в новый словарьcombined
.
- Внешний цикл (
-
Форматирование вывода: Мы добавляем запятые между элементами, избегая их в конце списка, что делает вывод аккуратным и соответствующим ожидаемому формату.
Заключение
При выполнении этого кода с использованием Ansible вы получите требуемый декартов продукт, что позволит вам эффективно работать со списками словарей для достижения нужного результата. Обратите внимание на необходимость учета различных пустых мест и форматирования, чтобы результат выглядел корректно и в соответствии с ожиданиями.