Ansible:将包含列表值的字典拆分为包含列表中单个元素作为值的字典列表



我需要将一个具有列表值的字典转换为一个字典列表。

给定:

my_dict:
key1: ["111", "222"]
key2: ["444", "555"]

所需输出:

my_list:
- key1: "111"
key2: "444"
- key1: "222"
key2: "555"

我试过了:

- set_fact:
my_list: "{{ my_list | default([]) + [{item.0.key: item.1}] }}"
loop: "{{ my_dict | dict2items | subelements('value') }}"

我得到了什么:

[
{
"key1": "111"
},
{
"key1": "222"
},
{
"key2": "444"
},
{
"key2": "555"
} 
]

感谢任何帮助和建议!

首先获取字典的键和值

keys: "{{ my_dict.keys()|list }}"
vals: "{{ my_dict.values()|list }}"

keys: [key1, key2]
vals:
- ['111', '222']
- ['444', '555']

转置

- set_fact:
tvals: "{{ tvals|d(vals.0)|zip(item)|map('flatten') }}"
loop: "{{ vals[1:] }}"

tvals:
- ['111', '444']
- ['222', '555']

创建字典列表

my_list: "{{ tvals|map('zip', keys)|
map('map', 'reverse')|
map('community.general.dict')|
list }}"

my_list:
- key1: '111'
key2: '444'
- key1: '222'
key2: '555'
指出
<一口>

  1. 完整剧本示例
- hosts: localhost
vars:
my_dict:
key1: ["111", "222"]
key2: ["444", "555"]
keys: "{{ my_dict.keys()|list }}"
vals: "{{ my_dict.values()|list }}"
my_list: "{{ tvals|map('zip', keys)|
map('map', 'reverse')|
map('community.general.dict')|
list }}"
tasks:
- set_fact:
tvals: "{{ tvals|d(vals.0)|zip(item)|map('flatten') }}"
loop: "{{ vals[1:] }}"
- debug:
var: my_list
  1. 您可以使用自定义过滤器来转置矩阵。例如,
shell> cat filter_plugins/numpy.py 
# All rights reserved (c) 2022, Vladimir Botka <vbotka@gmail.com>
# Simplified BSD License, https://opensource.org/licenses/BSD-2-Clause
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
from ansible.errors import AnsibleFilterError
from ansible.module_utils.common._collections_compat import Sequence
import json
import numpy

def numpy_transpose(arr):
if not isinstance(arr, Sequence):
raise AnsibleFilterError('First argument for numpy_transpose must be list. %s is %s' %
(arr, type(arr)))
arr1 = numpy.array(arr)
arr2 = arr1.transpose()
return json.dumps(arr2.tolist())

class FilterModule(object):
''' Ansible wrappers for Python NumPy methods '''
def filters(self):
return {
'numpy_transpose': numpy_transpose,
}

则可以避免迭代。例如,下面的剧本给出了相同的结果

- hosts: localhost
vars:
my_dict:
key1: ["111", "222"]
key2: ["444", "555"]
keys: "{{ my_dict.keys()|list }}"
vals: "{{ my_dict.values()|list }}"
tvals: "{{ vals|numpy_transpose()|from_yaml }}"
my_list: "{{ tvals|map('zip', keys)|
map('map', 'reverse')|
map('community.general.dict')|
list }}"
tasks:
- debug:
var: my_list
  1. 转位解释

让我们从矩阵2x2

开始
vals:
- ['111', '222']
- ['444', '555']

下面的任务

- set_fact:
tvals: "{{ tvals|d(vals.0)|zip(item) }}"
loop: "{{ vals[1:] }}"

给出step by step:

a)在迭代开始之前,变量tvals被赋值为默认值vals。0

vals.0: ['111', '222']

b)任务迭代列表vals[1:]。这些是数组中的所有行,除了第一行

vals[1:]:
- ['444', '555']

c)第一次,也是唯一一次,迭代压缩第一行和第二行。这是结果

vals.0|zip(vals.1):
- ['111', '444']
- ['222', '555']

我们继续看矩阵3x3

vals:
- ['111', '222', '333']
- ['444', '555', '666']
- ['777', '888', '999']

下面的任务

- set_fact:
tvals: "{{ tvals|d(vals.0)|zip(item)|map('flatten') }}"
loop: "{{ vals[1:] }}"

给出step by step:

a)在迭代开始之前,变量tvals被赋值为默认值vals。0

vals.0: ['111', '222', '333']

b)任务迭代列表vals[1:]

vals[1:]:
- ['444', '555', '666']
- ['777', '888', '999']

c)第一次迭代压缩第一行和第二行,并将其分配给tvals。过滤器flatten

行没有影响。
vals.0|zip(vals.1)|map('flatten'):
- ['111', '444']
- ['222', '555']
- ['333', '666']
d)下一个迭代zip和第三行
tvals|zip(vals.2):
- - ['111', '444']
- '777'
- - ['222', '555']
- '888'
- - ['333', '666']
- '999

e)这些线必须变平。这是结果

tvals|zip(vals.2)|map('flatten'):
- ['111', '444', '777']
- ['222', '555', '888']
- ['333', '666', '999']

相关内容

  • 没有找到相关文章