英文:
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
,我想要
- 在字典中搜索North_America,如果存在,收集它的ID。
- 使用North_America的ID,搜索具有相同值的键,并检查是否包含名称等于Texas的值。如果存在,收集Texas的ID
- 使用Texas的ID,搜索具有相同值的键,并检查是否包含名称等于Austin的值
- 对街道重复相同的过程...
最终目标是,如果搜索字符串"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
- Search the disc for North_America, if it exists collect it's ID.
- 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
- Using the id of Texas, search the key of the same value and check that it contains a value with name == Austin
- 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: "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
Output from the first debug is an empty list
ok: [localhost] => {
"group_id": []
}
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: "{{ dict(grouped.keys()|
zip(grouped.values()|
map('items2dict', key_name='Name', value_name='Id'))) }}"
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: "{{ 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') }}"
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论