I have a scenario where I need to convert this dictionary dict1
into dict2
in an Ansible playbook as shown below
dict1 = {'a':[1,2,3],'b':[4,5,6]}
dict2 = {1: 'a', 2: 'a', 3: 'a', 4: 'b', 5: 'b', 6: 'b'}
I tried with_nested
, with_items
but wasn't able to make it work.
A bit ugly but does the job without having to use set_fact
in a task which gives you freedom to declare the var anywhere (e.g. inventory, playbook, role defaults or vars, external file...).
The solution uses json_query
(which needs additional collection and pip module install on the controller, see documentation) because items2dict
is not able to use nested elements as key/value references.
map('flatten')
in the solution is a workaround for a "bug" in jmespath (library used by json_query
) which is unable to directly address tuples returned by subelements
: it transforms each element into a list where indexes can correctly be used in json_query
I did not spend time to see if indexes could be transformed to ints like asked in your requirement. As is, the final items2dict
transforms them back to string representations. If this is not acceptable you will have to search further.
Note: the below example will work in ansible >= 2.10. With an older version you will have to stick some intermediate list
filters inside the dict2
expression.
The playbook:
- hosts: localhost
gather_facts: false
vars:
dict1: {'a':[1,2,3],'b':[4,5,6]}
transform_q: >-
[*].{"key": [1], "value": [0].key}
dict2: "{{ dict1 | dict2items | subelements('value') | map('flatten')
| json_query(transform_q) | items2dict }}"
tasks:
- debug:
var: dict2
Gives:
PLAY [localhost] *******************************************************************************************
TASK [debug] ***********************************************************************************************
ok: [localhost] => {
"dict2": {
"1": "a",
"2": "a",
"3": "a",
"4": "b",
"5": "b",
"6": "b"
}
}
PLAY RECAP *************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0