list of lists, to list of dicts?

Hii

I have something like this in my vars:

test:

    • host1
  • fd99:9999::1
    • host1
  • 10.0.1.1
    • host2
  • fd99:9999::1
    • host2
  • 10.0.1.1
    • foo
  • fd99:9999::1
    • foo
  • 10.0.1.1
    • baz
  • fd99:9999::1
    • baz
  • 10.0.1.1

Each first and second list item should become keys in a dict, like this:

conv:

  • name: host1
    address: fd99:9999::1
  • name: host1
    address: 10.0.1.1
  • name: host2
    address: fd99:9999::1
  • name: host2
    address: 10.0.1.1
  • name: foo
    address: fd99:9999::1
  • name: foo
    address: 10.0.1.1
  • name: baz
    address: fd99:9999::1
  • name: baz
    address: 10.0.1.1

I tried a few things with mapping and filtering, but can’t see how to do it…
any suggestions? Ideally no tasks, just filters…

thx

  • name: list of list to list of dict

hosts: localhost

become: false

gather_facts: false

vars:

test:

    • host1
  • fd99:9999::1

    • host1
  • 10.0.1.1

    • host2
  • fd99:9999::1

    • host2
  • 10.0.1.1

    • foo
  • fd99:9999::1

    • foo
  • 10.0.1.1

    • baz
  • fd99:9999::1

    • baz
  • 10.0.1.1

tasks:

  • name: test

debug: var=test

  • name: list 2 dict

set_fact:

list2dict: “{{ list2dict|default() + [ thisdict ] }}”

loop: “{{ test }}”

vars:

thisdict: { name: “{{ item.0 }}”, addr: “{{ item.1 }}” }

  • name: list2dict

debug: var=list2dict

Walter

https://docs.ansible.com/ansible/latest/collections/community/general/dict_filter.html

This is an even more elegant solution using the community.general.dict module:

  • name: list2dict

set_fact:

list2dict: >-

{{ test | map(‘zip’, [‘name’, ‘addr’])

map(‘map’, ‘reverse’)

map(‘community.general.dict’) }}

  • name: list2dict

debug: var=list2dict

Walter

perfect, thx!!

That is elegant. Much better than the abomination I came up with:

---
# dick-visser-03.yml
- name: Add helper keys to list of dicts
  hosts: localhost
  connection: local
  gather_facts: no
  vars:
    test:
      - - host1
        - fd99:9999::1
      - - host1
        - 10.0.1.1
      - - host2
        - fd99:9999::1
      - - host2
        - 10.0.1.1
      - - foo
        - fd99:9999::1
      - - foo
        - 10.0.1.1
      - - baz
        - fd99:9999::1
      - - baz
        - 10.0.1.1
  tasks:
    - name: Dictify the test data - 1
      ansible.builtin.debug:
        msg:
          - 'test'
          - '{{ test }}'

          - '   test | map("map","community.general.dict_kv","value")'
          - '{{ test | map("map","community.general.dict_kv","value") }}'

          - '   test | map("map","community.general.dict_kv","value") | map("zip",[{"key":"name"},{"key":"address"}])'
          - '{{ test | map("map","community.general.dict_kv","value") | map("zip",[{"key":"name"},{"key":"address"}]) }}'

          - '   test
                > map("map","community.general.dict_kv","value")
                > map("zip",[{"key":"name"},{"key":"address"}])
                > map("map","flatten",1)
                > map("map","combine")'
          - '{{ test
                > map("map","community.general.dict_kv","value")
                > map("zip",[{"key":"name"},{"key":"address"}])
                > map("map","flatten",1)
                > map("map","combine") }}'

          - '   test
                > map("map","community.general.dict_kv","value")
                > map("zip",[{"key":"name"},{"key":"address"}])
                > map("map","flatten",1)
                > map("map","combine")
                > map("items2dict")'
          - '{{ test
                > map("map","community.general.dict_kv","value")
                > map("zip",[{"key":"name"},{"key":"address"}])
                > map("map","flatten",1)
                > map("map","combine")
                > map("items2dict") }}'

Thanks Todd. Honestly I came right off the dict module page that has an almost exact example.

Walter