将一个ansible列表的列表转换为一个字典列表。

huangapple go评论83阅读模式
英文:

Transforming an ansible list of lists to a list of dicts

问题

我终于学会了如何使用 product 创建嵌套列表,但我不喜欢必须通过索引访问结果。product 生成一个列表的列表,而我想要一个字典的列表。

例如,以下代码....

- name: experimenting
  hosts: localhost
  tasks:
  - name: Define some facts
    set_fact:
      people:
      - name: "Fred"
      - name: "John"
      animals:
      - name: "cat"

  - debug:
      msg: "{{ animals | product(people) }}"

...生成以下输出:

ok: [localhost] => {
    "msg": [
        [
            {
                "name": "cat"
            },
            {
                "name": "Fred"
            }
        ],
        [
            {
                "name": "cat"
            },
            {
                "name": "John"
            }
        ]
    ]
}

我该如何转换它,使其看起来像:

ok: [localhost] => {
    "msg": [
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "Fred"
            }
        },
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "John"
            }
        }
    ]
}

在C#中,我会使用LINQ的 Select 语句,但我在ansible世界中找不到等效的方法。

英文:

I finally learned how to do nested lists with product, but I don't like that I have to access the results by indices. product produces a list of lists, and I want a list of dicts.

For example, the following code....

- name: experimenting
  hosts: localhost
  tasks:
  - name: Define some facts
    set_fact:
      people:
      - name: "Fred"
      - name: "John"
      animals:
      - name: "cat"

  - debug:
      msg: "{{ animals | product(people)  }}"  

...produces the following output:

ok: [localhost] => {
    "msg": [
        [
            {
                "name": "cat"
            },
            {
                "name": "Fred"
            }
        ],
        [
            {
                "name": "cat"
            },
            {
                "name": "John"
            }
        ]
    ]
}

How can I transform that so it looks like:

ok: [localhost] => {
    "msg": [
        {
            animal: {
                name: "cat"
            },
            person: {
                name: "Fred"
            }
        },
        {
            animal: {
                name: "cat"
            },
            person: {
                name: "John"
            }
        }
    ]
}

In C#, I would use the LINQ Select statement, but I can't find the equivalent of that in ansible world.

答案1

得分: 1

以下是翻译好的内容:

这个示例没有使用 chatGPT,因为(至少暂时)受到网站规则的限制。此外,它对您最初的问题进行了一些修复,以遵循最佳实践,如仅在需要时使用 set_facts,以及仅在必要时在任务中进行循环。

这个自解释的剧本带有中间调试,应该很容易理解并提供您期望的结果:

---
- name: 实验
  hosts: localhost
  gather_facts: false

  vars:
    
    people:
      - name: "Fred"
      - name: "John"
    
    animals:
      - name: "cat"

    people_as_dict: "{{ ['people: '] | product(people) | map('join') | map('from_yaml') }}"

    animals_as_dict: "{{ ['animal: '] | product(animals) | map('join') | map('from_yaml') }}"

    people_animals: "{{ people_as_dict | product(animals_as_dict) | map('combine') }}"

  tasks:
    - name: 将人员列表转换为每个元素都是一个字典
      ansible.builtin.debug:
        var: people_as_dict

    - name: 对动物执行与上述相同的操作
      ansible.builtin.debug:
        var: animals_as_dict

    - name: 组合每个元素以获得预期的结果
      ansible.builtin.debug:
        var: people_animals

演示运行:

PLAY [实验] ******************************************************************************************************************************************************************************************

TASK [将人员列表转换为每个元素都是一个字典] *********************************************************************************************************************************************************
ok: [localhost] => {
    "people_as_dict": [
        {
            "people": {
                "name": "Fred"
            }
        },
        {
            "people": {
                "name": "John"
            }
        }
    ]
}

TASK [对动物执行与上述相同的操作] *****************************************************************************************************************************************************************
ok: [localhost] => {
    "animals_as_dict": [
        {
            "animal": {
                "name": "cat"
            }
        }
    ]
}

TASK [组合每个元素以获得预期的结果] *****************************************************************************************************************************************************************
ok: [localhost] => {
    "people_animals": [
        {
            "animal": {
                "name": "cat"
            },
            "people": {
                "name": "Fred"
            }
        },
        {
            "animal": {
                "name": "cat"
            },
            "people": {
                "name": "John"
            }
        }
    ]
}

PLAY RECAP ******************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
英文:

That one is not written using chatGPT as it is (at least temporarily) forbidden by site rules. Moreover, it includes some fixes on your initial question to respect best practice like using set_facts only when it is needed and looping in a task only when necessary.

This self explanatory playbook with intermediate debug should be quite easy to get and gives what you expect:

---
- name: experiment
  hosts: localhost
  gather_facts: false

  vars:
    
    people:
      - name: "Fred"
      - name: "John"
    
    animals:
      - name: "cat"

    people_as_dict: "{{ ['people: '] | product(people) | map('join') | map('from_yaml') }}"

    animals_as_dict: "{{ ['animal: '] | product(animals) | map('join') | map('from_yaml') }}"

    people_animals: "{{ people_as_dict | product(animals_as_dict) | map('combine') }}"

  tasks:
    - name: Tranform people list so that each element is a dict
      ansible.builtin.debug:
        var: people_as_dict

    - name: Do the same thing as above with animals
      ansible.builtin.debug:
        var: animals_as_dict

    - name: combine every element to get expected resutl
      ansible.builtin.debug:
        var: people_animals

Demo run:

PLAY [experiment] ******************************************************************************************************************************************************************************************

TASK [Tranform people list so that each element is a dict] *************************************************************************************************************************************************
ok: [localhost] => {
    "people_as_dict": [
        {
            "people": {
                "name": "Fred"
            }
        },
        {
            "people": {
                "name": "John"
            }
        }
    ]
}

TASK [Do the same thing as above with animals] *************************************************************************************************************************************************************
ok: [localhost] => {
    "animals_as_dict": [
        {
            "animal": {
                "name": "cat"
            }
        }
    ]
}

TASK [combine every element to get expected resutl] ********************************************************************************************************************************************************
ok: [localhost] => {
    "people_animals": [
        {
            "animal": {
                "name": "cat"
            },
            "people": {
                "name": "Fred"
            }
        },
        {
            "animal": {
                "name": "cat"
            },
            "people": {
                "name": "John"
            }
        }
    ]
}

PLAY RECAP *************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

答案2

得分: -3

我明白了。

- name: 实验
  hosts: localhost
  tasks:
  - name: 定义一些事实
    set_fact:
      people:
      - name: "Fred"
      - name: "John"
      animals:
      - name: "cat"

  - name: 转换数据
    set_fact:
      transformed: "{{ transformed | default([]) + [{'animal': item[0], 'person': item[1] }] }}"
    loop: "{{ animals | product(people) }}"

  - debug:
      msg: "{{ transformed }}"

...生成:

ok: [localhost] => {
    "msg": [
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "Fred"
            }
        },
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "John"
            }
        }
    ]
}
英文:

I figured it out.

- name: experimenting
  hosts: localhost
  tasks:
  - name: Define some facts
    set_fact:
      people:
      - name: "Fred"
      - name: "John"
      animals:
      - name: "cat"

  - name: Transform the data
    set_fact:
      transformed: "{{ transformed | default([]) + [{'animal': item[0], 'person': item[1] }] }}"
    loop: "{{ animals | product(people) }}"

  - debug:
      msg: "{{ transformed }}"

...produces:

ok: [localhost] => {
    "msg": [
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "Fred"
            }
        },
        {
            "animal": {
                "name": "cat"
            },
            "person": {
                "name": "John"
            }
        }
    ]
}

huangapple
  • 本文由 发表于 2023年7月31日 21:11:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803975.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定