Ansible – 在字典中识别键,当键值是字典的列表时

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

Ansible - Identify Key in dictionary when Key values are lists of dicts

问题

以下是您要翻译的内容:

我有以下的字典

```yaml
  grouped:
    10000:
    - {Id: 10001, Name: North_America, Parent_Id: 10000, Type: Country}
    10001:
    - {Id: 10011, Name: Maine, Parent_Id: 10001, Type: State}
    - {Id: 10012, Name: Colorado, Parent_Id: 10001, Type: State}
    - {Id: 10013, Name: Texas, Parent_Id: 10001, Type: State}
    10011:
    - {Id: 10101, Name: Augusta, Parent_Id: 10011, Type: City}
    - {Id: 10102, Name: Portland, Parent_Id: 10011, Type: City}
    10012:
    - {Id: 10103, Name: Denver, Parent_Id: 10012, Type: City}
    10013:
    - {Id: 10104, Name: Austin, Parent_Id: 10013, Type: City}
    - {Id: 10105, Name: Houston, Parent_Id: 10013, Type: City}
    10101:
    - {Id: 11001, Name: First_st, Parent_Id: 10101, Type: Street}
    - {Id: 11002, Name: Second_st, Parent_Id: 10101, Type: Street}
    10102:
    - {Id: 11003, Name: First_st, Parent_Id: 10102, Type: Street}
    - {Id: 11004, Name: Second_st, Parent_Id: 10102, Type: Street}
    10104:
    - {Id: 11005, Name: First_st, Parent_Id: 10104, Type: Street}
    - {Id: 11006, Name: Second_st, Parent_Id: 10104, Type: Street}

如果我有一个包含Country-State-City-Street的字符串,例如North_America-Texas-Austin-First_st,我想要

  1. 在字典中搜索North_America,如果存在,收集它的ID。
  2. 使用North_America的ID,搜索具有相同值的键,并检查是否包含名称等于Texas的值。如果存在,收集Texas的ID
  3. 使用Texas的ID,搜索具有相同值的键,并检查是否包含名称等于Austin的值
  4. 对街道重复相同的过程...

最终目标是,如果搜索字符串"North_America-Texas-Austin-Third_st"提供且在字典中不存在,它将被添加

第一步是识别所需的键,我尝试使用json_queries和selectattr来完成这个任务,但都不起作用

---
  hosts: localhost
  gather_facts: false
  connection: local
  vars:
    target: "North_America-Colorado-Denver-First_st"

  tasks:
    - name: Get the id using json filter and jmespath query
      set_fact:
        group_id: "{{ grouped | json_query(ID_query) | map(attribute='key') }}"
      vars:
        ID_query: '[?[*].Name == `North-America`]'
    - debug: var=group_id

    - name: Get the id using selectattr
      set_fact:
        group_id2: "{{ grouped | dict2items | selectattr('Name', 'search', 'North_America') }}"
    - debug: var=group_id2

第一个调试输出是一个空列表

ok: [localhost] => {
    "group_id": []
}

第二个调试输出说字典对象没有Name属性


<details>
<summary>英文:</summary>

I have the following dictionary

```yaml
  grouped:
    10000:
    - {Id: 10001, Name: North_America, Parent_Id: 10000, Type: Country}
    10001:
    - {Id: 10011, Name: Maine, Parent_Id: 10001, Type: State}
    - {Id: 10012, Name: Colorado, Parent_Id: 10001, Type: State}
    - {Id: 10013, Name: Texas, Parent_Id: 10001, Type: State}
    10011:
    - {Id: 10101, Name: Augusta, Parent_Id: 10011, Type: City}
    - {Id: 10102, Name: Portland, Parent_Id: 10011, Type: City}
    10012:
    - {Id: 10103, Name: Denver, Parent_Id: 10012, Type: City}
    10013:
    - {Id: 10104, Name: Austin, Parent_Id: 10013, Type: City}
    - {Id: 10105, Name: Houston, Parent_Id: 10013, Type: City}
    10101:
    - {Id: 11001, Name: First_st, Parent_Id: 10101, Type: Street}
    - {Id: 11002, Name: Second_st, Parent_Id: 10101, Type: Street}
    10102:
    - {Id: 11003, Name: First_st, Parent_Id: 10102, Type: Street}
    - {Id: 11004, Name: Second_st, Parent_Id: 10102, Type: Street}
    10104:
    - {Id: 11005, Name: First_st, Parent_Id: 10104, Type: Street}
    - {Id: 11006, Name: Second_st, Parent_Id: 10104, Type: Street}

If I'm given a string containing Country-State-City-Street, eg North_America-Texas-Austin-First_st, I want to

  1. Search the disc for North_America, if it exists collect it's ID.
  2. Using the ID of North_America, search the Key of the same value and check that it contains a value with name == Texas. If it exists, collect the ID of Texas
  3. Using the id of Texas, search the key of the same value and check that it contains a value with name == Austin
  4. Repeat for street...

The end goal, if the search string "North_America-Texas-Austin-Third_st" is provided and it does not exist in the dict, it will be added

First step is to identify the required Key, I've attempted json_queries and selectattr to do this but none work

---
  hosts: localhost
  gather_facts: false
  connection: local
  vars:
    target: &quot;North_America-Colorado-Denver-First_st&quot;

  tasks:
    - name: Get the id using json filter and jmespath query
      set_fact:
        group_id: &quot;{{ grouped | json_query(ID_query) | map(attribute=&#39;key&#39;) }}&quot;
      vars:
        ID_query: &#39;[?[*].Name == `North-America`]&#39;
    - debug: var=group_id

    - name: Get the id using selectattr
      set_fact:
        group_id2: &quot;{{ grouped | dict2items | selectattr(&#39;Name&#39;, &#39;search&#39;, &#39;North_America&#39;) }}&quot;
    - debug: var=group_id2

Output from the first debug is an empty list

ok: [localhost] =&gt; {
    &quot;group_id&quot;: []
}

Output from the second debug says that the dict object has no attribute Name

答案1

得分: 0

创建一个*ids*的字典

```yaml
  ids: "{{ dict(grouped.keys()|
                zip(grouped.values()|
                    map('items2dict', key_name='Name', value_name='Id'))) }}"

得到

  ids:
    10000: {North_America: 10001}
    10001: {Colorado: 10012, Maine: 10011, Texas: 10013}
    10011: {Augusta: 10101, Portland: 10102}
    10012: {Denver: 10103}
    10013: {Austin: 10104, Houston: 10105}
    10101: {First_st: 11001, Second_st: 11002}
    10102: {First_st: 11003, Second_st: 11004}
    10104: {First_st: 11005, Second_st: 11006}

然后,使用它。例如

    - debug:
        msg: "{{ item }} [{{ target_ok }}] {{ target_id }}"
      loop:
        - North_America-Colorado-Denver-First_st
        - North_America-Texas-Austin-First_st
        - North_America-Texas-Austin-Third_st
      vars:
        f: "{{ item|split('-') }}"
        country: "{{ ids.10000[f.0]|d('undef') }}"
        state: "{{ ids[country|int][f.1]|d('undef') }}"
        city: "{{ ids[state|int][f.2]|d('undef') }}"
        street: "{{ ids[city|int][f.3]|d('undef') }}"
        target_id: "{{ country }} {{ state }} {{ city }} {{ street }}"
        target_ok: "{{ ('undef' in target_id.split())|ternary('KO', 'OK') }}"

得到简略版

  msg: North_America-Colorado-Denver-First_st [KO] 10001 10012 10103 undef
  msg: North_America-Texas-Austin-First_st [OK] 10001 10013 10104 11005
  msg: North_America-Texas-Austin-Third_st [KO] 10001 10013 10104 undef
英文:

Create a dictionary of ids

  ids: &quot;{{ dict(grouped.keys()|
                zip(grouped.values()|
                    map(&#39;items2dict&#39;, key_name=&#39;Name&#39;, value_name=&#39;Id&#39;))) }}&quot;

gives

  ids:
    10000: {North_America: 10001}
    10001: {Colorado: 10012, Maine: 10011, Texas: 10013}
    10011: {Augusta: 10101, Portland: 10102}
    10012: {Denver: 10103}
    10013: {Austin: 10104, Houston: 10105}
    10101: {First_st: 11001, Second_st: 11002}
    10102: {First_st: 11003, Second_st: 11004}
    10104: {First_st: 11005, Second_st: 11006}

Then, use it. For example

    - debug:
        msg: &quot;{{ item }} [{{ target_ok }}] {{ target_id }}&quot;
      loop:
        - North_America-Colorado-Denver-First_st
        - North_America-Texas-Austin-First_st
        - North_America-Texas-Austin-Third_st
      vars:
        f: &quot;{{ item|split(&#39;-&#39;) }}&quot;
        country: &quot;{{ ids.10000[f.0]|d(&#39;undef&#39;) }}&quot;
        state: &quot;{{ ids[country|int][f.1]|d(&#39;undef&#39;) }}&quot;
        city: &quot;{{ ids[state|int][f.2]|d(&#39;undef&#39;) }}&quot;
        street: &quot;{{ ids[city|int][f.3]|d(&#39;undef&#39;) }}&quot;
        target_id: &quot;{{ country }} {{ state }} {{ city }} {{ street }}&quot;
        target_ok: &quot;{{ (&#39;undef&#39; in target_id.split())|ternary(&#39;KO&#39;, &#39;OK&#39;) }}&quot;

gives abridged

  msg: North_America-Colorado-Denver-First_st [KO] 10001 10012 10103 undef
  msg: North_America-Texas-Austin-First_st [OK] 10001 10013 10104 11005
  msg: North_America-Texas-Austin-Third_st [KO] 10001 10013 10104 undef

huangapple
  • 本文由 发表于 2023年8月4日 22:13:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76836728.html
匿名

发表评论

匿名网友

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

确定