【问题标题】:Iterate dict Ansible, each key multiple values迭代dict Ansible,每个key多个值
【发布时间】:2021-06-13 16:15:15
【问题描述】:

我有一个这样的字典:

  distr:
    Alice:
    - Avocado
    - Cherries
    Bob:
    - Apple
    David:
    - Pineapple
    - Watermelon
    John:
    - Banana
    - Mango
    Shara:
    - Orange
    - Peach

现在我想用每个组合执行一个任务。

像这样:

Alice eats Avocado
Alice eats Cherries
Bob eats Apple
David eats Pineapple
David eats Watermelon
...

我的ansible是这样的:

- name: Debug
  debug:
    msg: {{ item.key }} eats {{ item }}
  with_items: "{{ lookup('dict', distr) }}"

结果:

TASK [Debug] *******************************************************************************************************************************************************************************************************************************************
ok: [localhost] => (item={'key': 'Alice ', 'value': ['Avocado', 'Cherries']}) => {
    "msg": "Alice eats ['Avocado', 'Cherries']"
}
ok: [localhost] => (item={'key': 'Bob ', 'value': ['Apple']}) => {
    "msg": "Bob eats ['Apple']"
}
ok: [localhost] => (item={'key': 'David ', 'value': ['Pineapple', 'Watermelon']}) => {
    "msg": "David eats ['Pineapple', 'Watermelon']"
}

我尝试了子元素和其他类型的循环,但没有运气。我觉得这很简单。

【问题讨论】:

    标签: loops dictionary ansible


    【解决方案1】:

    我们需要处理您的数据以将其转化为更有用的结构。我们想要一个由(person, food) 元组组成的平面列表,我们可以使用product 过滤器到达那里,它返回两个列表的叉积。例如,表达式["Alice"]|product(["Avocado", "Cherries"]) 计算为[["Alice", "Avocado"], ["Alice", "Cherries"]]

    我们可以使用循环的set_fact 任务来创建我们的列表:

    - set_fact:
        cross: "{{ cross + [item[0]]|product(item[1])|list }}"
      loop: "{{ distr.items()|list }}"
      vars:
        cross: []
    

    上述任务遍历你的每个 (key, values) 元组 字典并将键和值的叉积附加到 新列表,cross。结果如下所示:

    "cross": [
        [
            "Alice",
            "Avocado"
        ],
        [
            "Alice",
            "Cherries"
        ],
        [
            "Bob",
            "Apple"
        ],
        [
            "David",
            "Pineapple"
        ],
        [
            "David",
            "Watermelon"
        ],
        [
            "John",
            "Banana"
        ],
        [
            "John",
            "Mango"
        ],
        [
            "Shara",
            "Orange"
        ],
        [
            "Shara",
            "Peach"
        ]
    ]
    

    将所有这些放在一起,我们得到:

    - hosts: localhost
      gather_facts: false
      vars:
        distr:
          Alice:
            - Avocado
            - Cherries
          Bob:
            - Apple
          David:
            - Pineapple
            - Watermelon
          John:
            - Banana
            - Mango
          Shara:
            - Orange
            - Peach
    
      tasks:
        - set_fact:
            cross: "{{ cross + [item[0]]|product(item[1])|list }}"
          loop: "{{ distr.items()|list }}"
          vars:
            cross: []
    
        - debug:
            msg: "{{ item[0] }} eats {{ item[1] }}"
          loop: "{{ cross }}"
    

    运行上述剧本的输出是:

    PLAY [localhost] *****************************************************************************************************************************************************************************
    
    TASK [set_fact] ******************************************************************************************************************************************************************************
    ok: [localhost] => (item=['Alice', ['Avocado', 'Cherries']])
    ok: [localhost] => (item=['Bob', ['Apple']])
    ok: [localhost] => (item=['David', ['Pineapple', 'Watermelon']])
    ok: [localhost] => (item=['John', ['Banana', 'Mango']])
    ok: [localhost] => (item=['Shara', ['Orange', 'Peach']])
    
    TASK [debug] *********************************************************************************************************************************************************************************
    ok: [localhost] => (item=['Alice', 'Avocado']) => {
        "msg": "Alice eats Avocado"
    }
    ok: [localhost] => (item=['Alice', 'Cherries']) => {
        "msg": "Alice eats Cherries"
    }
    ok: [localhost] => (item=['Bob', 'Apple']) => {
        "msg": "Bob eats Apple"
    }
    ok: [localhost] => (item=['David', 'Pineapple']) => {
        "msg": "David eats Pineapple"
    }
    ok: [localhost] => (item=['David', 'Watermelon']) => {
        "msg": "David eats Watermelon"
    }
    ok: [localhost] => (item=['John', 'Banana']) => {
        "msg": "John eats Banana"
    }
    ok: [localhost] => (item=['John', 'Mango']) => {
        "msg": "John eats Mango"
    }
    ok: [localhost] => (item=['Shara', 'Orange']) => {
        "msg": "Shara eats Orange"
    }
    ok: [localhost] => (item=['Shara', 'Peach']) => {
        "msg": "Shara eats Peach"
    }
    
    PLAY RECAP ***********************************************************************************************************************************************************************************
    localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    

    【讨论】:

    • 完美工作!非常感谢!