如何使用列表中的项目创建一个新属性,并将其追加回相同的字典列表?

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

How to create a new attribute using items from a list and append it back to the same list of dictionaries?

问题

我可以帮您翻译代码部分:

- set_fact:
    FullName: "{{ item.FirstName + ' ' + item.LastName }}"
  loop: "{{ data }}"

请注意,您可以使用上面的代码将 FullName 属性添加到每个字典中,但这将结果存储在 ansible_facts.FullName 中。如果您想要将结果存储在 item.FullName 中,您可以尝试以下方法:

- set_fact:
    item.FullName: "{{ item.FirstName + ' ' + item.LastName }}"
  loop: "{{ data }}"

这应该会将 FullName 属性添加到每个字典中的 item 变量中。希望这可以帮助您达到预期的输出。

英文:

I have this list:

{
  "data": [
    {
      "ClassType": "Part Time",
      "FirstName": "Monice",
      "LastName": "Lee"
    },
    {
      "ClassType": "Full Time",
      "FirstName": "Henry Daley",
      "LastName": "Brown"
    }
  ]
}

How do I create a new attribute FullName, which value would be FirstName + ' ' + LastName and append this to all the dictionaries of the list?

Expected output:

{
 "data": [
    {
        "ClassType": "Part Time",
        "FirstName": "Monice",
        "LastName": "Lee",
        "FullName": "Monice Lee"
    },
    {
        "ClassType": "Full Time",
        "FirstName": "Henry Daley",
        "LastName": "Brown",
        "FullName": "Henry Daley Brown"
    }
 ]
}

I tried this approach:

- set_fact:
    FullName: "{{ item.FirstName + ' ' + item.LastName }}"
  loop: "{{ data }}"

However, the new variable ended up appearing under ansible_facts.FullName and not item.FullName.

Output

ok: [localhost] => (item={'FirstName': 'Henry Daley', 'LastName': 'Brown', 'ClassType': 'Full Time'}) => {
    "ansible_facts": {
        "FullName": "Henry Daley Brown"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "ClassType": "Full Time",
        "FirstName": "Henry Daley",
        "LastName": "Brown"
    }
}
ok: [localhost] => (item={'FirstName': 'Monice', 'LastName': 'Lee', 'ClassType': 'Part Time'}) => {
    "ansible_facts": {
        "FullName": "Monice Lee"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "item": {
        "ClassType": "Part Time",
        "FirstName": "Monice",
        "LastName": "Lee"
    }
}

How can I create/append this FullName attribute each dictionary of the list?

答案1

得分: 3

你可以使用 JMESPath 的 join 函数来更新你的字典。

给定的任务:

- set_fact:
    data: >-
      {{
        data | json_query("
        [].{
          ClassType: ClassType,
          FirstName: FirstName,
          LastName: LastName,
          FullName: join(' ', [FirstName, LastName])}
        ")
      }}
  vars:
    data:
      - ClassType: Full Time
        FirstName: Henry Daley
        LastName: Brown
      - ClassType: Part Time
        FirstName: Monice
        LastName: Lee

你的 data 变量将根据你的需求更新为:

ok: [localhost] => changed=false 
  ansible_facts:
    data:
    - ClassType: Full Time
      FirstName: Henry Daley
      FullName: Henry Daley Brown
      LastName: Brown
    - ClassType: Part Time
      FirstName: Monice
      FullName: Monice Lee
      LastName: Lee

注意:上述输出是在运行带有 -v 选项的 Playbook 时生成的,其中包括了 set_fact 任务的结果等有用信息。

英文:

You could use the join function of JMESPath to update your dictionary.

Given the task:

- set_fact:
    data: >-
      {{
        data | json_query("
        [].{
          ClassType: ClassType,
          FirstName: FirstName,
          LastName: LastName,
          FullName: join(' ', [FirstName, LastName])}
        ")
      }}
  vars:
    data:
      - ClassType: Full Time
        FirstName: Henry Daley
        LastName: Brown
      - ClassType: Part Time
        FirstName: Monice
        LastName: Lee

Your data variable would be updated according to your need:

ok: [localhost] => changed=false 
  ansible_facts:
    data:
    - ClassType: Full Time
      FirstName: Henry Daley
      FullName: Henry Daley Brown
      LastName: Brown
    - ClassType: Part Time
      FirstName: Monice
      FullName: Monice Lee
      LastName: Lee

<sup>Note: the above output have been generated running the playbook with the option -v, which, amongst other useful information, shows the result of a set_fact task.</sup>

答案2

得分: 2

Create list *update*

```yaml
  update: "{{ data|json_query('[].[FirstName, LastName]')|
                   map('join', ' ')|
                   map('community.general.dict_kv','FullName') }}"

Optionally, the query below gives the same result

  fn_query: "[].{FullName: join(' ', [FirstName, LastName])}"
  update: "{{ data|json_query(fn_query) }}"


gives

  update:
  - FullName: Monice Lee
  - FullName: Henry Daley Brown

Update data

    - set_fact:
        data: "{{ data|zip(update)|map('combine') }}"

gives

  data:
  - ClassType: Part Time
    FirstName: Monice
    FullName: Monice Lee
    LastName: Lee
  - ClassType: Full Time
    FirstName: Henry Daley
    FullName: Henry Daley Brown
    LastName: Brown

Example of a complete playbook for testing

- hosts: localhost

  vars:

    data:
    - ClassType: Part Time
      FirstName: Monice
      LastName: Lee
    - ClassType: Full Time
      FirstName: Henry Daley
      LastName: Brown

    update: "{{ data|json_query('[].[FirstName, LastName]')|
                     map('join', ' ')|
                     map('community.general.dict_kv','FullName') }}"

  tasks:

    - debug:
        var: update
    - set_fact:
        data: "{{ data|zip(update)|map('combine') }}"
    - debug:
        var: data


```

英文:

Create list update

  update: &quot;{{ data|json_query(&#39;[].[FirstName, LastName]&#39;)|
                   map(&#39;join&#39;, &#39; &#39;)|
                   map(&#39;community.general.dict_kv&#39;,&#39;FullName&#39;) }}&quot;

<hr>

<sup>

Optionally, the query below gives the same result

  fn_query: &quot;[].{FullName: join(&#39; &#39;, [FirstName, LastName])}&quot;
  update: &quot;{{ data|json_query(fn_query) }}&quot;

</sup>

<hr>

gives

  update:
  - FullName: Monice Lee
  - FullName: Henry Daley Brown

Update data

    - set_fact:
        data: &quot;{{ data|zip(update)|map(&#39;combine&#39;) }}&quot;

gives

  data:
  - ClassType: Part Time
    FirstName: Monice
    FullName: Monice Lee
    LastName: Lee
  - ClassType: Full Time
    FirstName: Henry Daley
    FullName: Henry Daley Brown
    LastName: Brown

<hr>

<sup>

Example of a complete playbook for testing

- hosts: localhost

  vars:

    data:
    - ClassType: Part Time
      FirstName: Monice
      LastName: Lee
    - ClassType: Full Time
      FirstName: Henry Daley
      LastName: Brown

    update: &quot;{{ data|json_query(&#39;[].[FirstName, LastName]&#39;)|
                     map(&#39;join&#39;, &#39; &#39;)|
                     map(&#39;community.general.dict_kv&#39;,&#39;FullName&#39;) }}&quot;

  tasks:

    - debug:
        var: update
    - set_fact:
        data: &quot;{{ data|zip(update)|map(&#39;combine&#39;) }}&quot;
    - debug:
        var: data

</sup>

答案3

得分: 1

根据您的初始帖子

> ... 它最终出现在 ansible_facts.FullName 而不是 item.FullName 下...

这是正确的,也是预期的行为。

> 我如何将这个 FullName 变量创建/附加到 item 变量列表中

简短回答,你不能。至少不以那种方式,或者不更改 loop 的 Python 代码的情况下。这是因为循环变量不受任务的控制。可以考虑循环代码围绕任务代码。任务代码不知道外部有一个循环存在。

如果对更多细节或调试感兴趣,您可以查看在Ansible的交互式调试器中打印 item

解决您的问题的方法将是进行更复杂的数据操作,而不使用循环,并在其他答案中显示。

英文:

According your initial post

> ... it ended up appearing under ansible_facts.FullName and not item.FullName ...

That's correct and the expected behavior.

> How can I create/append this FullName variable to the list of item variables

Short answer, you can't. At least not in that way and or without changing the Python code of loop. This is because the loop variables are not under the control of the task. One could think about of that that the loop code is surrounding the task code. The task code is not aware of that there is a loop outside.

If interested in more details or debugging you may have a look into Print item from interactive debugger in Ansible.

The solution for your problem will be a more complex data manipulation without a loop and is shown in the other answers here.

huangapple
  • 本文由 发表于 2023年6月13日 14:56:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76462349.html
匿名

发表评论

匿名网友

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

确定