我正在寻求帮助,以特定方式合并两本词典。如果您能提供任何想法,我将不胜感激。
我有两个这样的词典:第一个词典:
servers:
server1:
Property1: A
Property2: B
Property3: C
server2:
Property1: A
Property2: B
Property3: C
第二個錄音:
management:
server1: ip1_addr
server2: ip2_addr
期望结果:
servers:
server1:
Property1: A
Property2: B
Property3: C
Property4: ip1_addr
server2:
Property1: A
Property2: B
Property3: C
Property4: ip2_addr
或者我可能选择了错误的路径,我所需要的只是一次循环两个字典,以获取 server1 键下的 ip1_addr 和 server2 键下的 ip2_addr
答案1
还有更多选择:
- 转换字典管理
- set_fact:
mgmt: "{{ mgmt|d({})|
combine({item.key: {'Property4': item.value}}) }}"
loop: "{{ management|dict2items }}"
如果您想避免迭代使用:
a) 过滤器社区.general.dict_kv
mgmt: "{{ dict(management.keys()|
zip(management.values()|
map('community.general.dict_kv', 'Property4'))) }}"
b) 过滤器社区.general.json_query
mgmt: "{{ dict(management|dict2items|
json_query('[].[key, {Property4: value}]')) }}"
C)金贾
mgmt_str: |
{% for k,v in management.items() %}
{{ k }}:
Property4: {{ v }}
{% endfor %}
mgmt: "{{ mgmt_str|from_yaml }}"
所有选项都会产生相同的结果
mgmt:
server1:
Property4: ip1_addr
server2:
Property4: ip2_addr
然后,结合字典
srvs: "{{ servers|combine(mgmt, recursive=True) }}"
给出了期望的结果
srvs:
server1:
Property1: A
Property2: B
Property3: C
Property4: ip1_addr
server2:
Property1: A
Property2: B
Property3: C
Property4: ip2_addr
完整测试剧本的示例
- hosts: localhost
vars:
servers:
server1:
Property1: A
Property2: B
Property3: C
server2:
Property1: A
Property2: B
Property3: C
management:
server1: ip1_addr
server2: ip2_addr
mgmt: "{{ dict(management.keys()|
zip(management.values()|
map('community.general.dict_kv', 'Property4'))) }}"
srvs: "{{ servers|combine(mgmt, recursive=True) }}"
tasks:
- debug:
var: mgmt
- debug:
var: srvs
- 使用 Jinja 创建 YAML 结构并使用过滤器进行转换来自_yaml. 声明服务端下面给出了相同的结果
srvs_str: |
{% for k,v in servers.items() %}
{{ k }}:
{{ v|combine({'Property4': management[k]}) }}
{% endfor %}
srvs: "{{ srvs_str|from_yaml }}"
- 如果要迭代结果,将两个字典都转换为列表会更容易
- set_fact:
mgmt_list: "{{ mgmt_list|d([]) +
[{'server': item.key, 'Property4': item.value}] }}"
loop: "{{ management|dict2items }}"
- set_fact:
srvs_list: "{{ srvs_list|d([]) +
[{'server': item.key}|combine(item.value)] }}"
loop: "{{ servers|dict2items }}"
如果你想避免迭代使用json_查询
mgmt_list: "{{ management|dict2items(key_name='server',
value_name='Property4') }}"
srvs_list: "{{ servers|dict2items|
json_query('[].merge({server: key}, value)') }}"
给
mgmt_list:
- Property4: ip1_addr
server: server1
- Property4: ip2_addr
server: server2
srvs_list:
- Property1: A
Property2: B
Property3: C
server: server1
- Property1: A
Property2: B
Property3: C
server: server2
然后使用社区.一般筛选社区.general.lists_mergeby
srvs: "{{ srvs_list|community.general.lists_mergeby(mgmt_list, 'server') }}"
给出一个列表,而不是预期的字典
srvs:
- Property1: A
Property2: B
Property3: C
Property4: ip1_addr
server: server1
- Property1: A
Property2: B
Property3: C
Property4: ip2_addr
server: server2
您可以将列表转换为字典
srvs_dict: "{{ dict(srvs|map(attribute='server')|zip(srvs)) }}"
, 或者
srvs_dict: "{{ dict(srvs|json_query('[].[server, @]')) }}"
两种选择的结果相同
srvs_dict:
server1:
Property1: A
Property2: B
Property3: C
Property4: ip1_addr
server: server1
server2:
Property1: A
Property2: B
Property3: C
Property4: ip2_addr
server: server2
完整测试剧本的示例
- hosts: localhost
vars:
servers:
server1:
Property1: A
Property2: B
Property3: C
server2:
Property1: A
Property2: B
Property3: C
management:
server1: ip1_addr
server2: ip2_addr
mgmt_list: "{{ management|dict2items(key_name='server',
value_name='Property4') }}"
srvs_list: "{{ servers|dict2items|
json_query('[].merge({server: key}, value)') }}"
srvs: "{{ srvs_list|community.general.lists_mergeby(mgmt_list, 'server') }}"
tasks:
- debug:
var: mgmt_list
- debug:
var: srvs_list
- debug:
var: srvs