Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
628 views
in Technique[技术] by (71.8m points)

scripting - Flattening and filtering a complex structure in ansible - dict of list of dict

I have data that is represented in this manner:

 {
    "key1": [{
      "name": "some name1",
      "index": "some idx1"
    },
    {
      "name": "some name2",
      "index": "some idx2"
    },
    {
      "name": "some name3",
      "index": "some idx3"
    }],
    "key2": [{
      "name": "some name4",
      "index": "some idx4"
    },
    {
      "name": "some name5",
      "index": "some idx5"
    },
    {
      "name": "some name6",
      "index": "some idx6"
    }]
}    

I would like to convert the above to this, which is basically a dictionary with the existing key to a list of the indices.

{ 
      "key1": [some idx1, some idx2, some idx3],
      "key2": [some idx4, some idx5, some idx6]
}

I have seen a couple of examples using map, extract and combine, but couldn't quite get it to work as yet. I was however able to do it using jinja, the code is below. My question is, what is the best way to accomplish the above. What is the recommended best practice with regards to this kind of things - is there any reason why more complex operations shouldn't be done using jinja2 (given that the one liners i have seen are overly complex and probably would be difficult for others to figure out - consequently making the script difficult to maintain).

here is the code that does the trick, but again, not sure if the best way of accomplishing this:

- hosts: local
  tags: test1
  gather_facts: False
  vars:
    dict1:
      key1:
        - { name: some name1, index: some idx1 }
        - { name: some name2, index: some idx2 }
        - { name: some name3, index: some idx3 }
      key2:
        - { name: some name4, index: some idx4 }
        - { name: some name5, index: some idx5 }
        - { name: some name6, index: some idx6 }
  tasks:      
  - name: "dict of list of dict"
    set_fact:
      index_map: |
        {% set map = dict() %}
        {% for k,v in dict1.iteritems() %}
          {% set x=map.__setitem__(k, []) %}
          {% for item in v %}
            {% set x= map[k].append(item.name) %}
          {% endfor %}
        {% endfor %}
        {{ map }}
  - debug: 
      msg: "{{ index_map }}"

To expand on the problem im trying to solve a bit more: Given an 'index' , i want to find the key it is associated it with. The target structure would allow me to do that a bit easier i think. so either a dict of key to a list of index, or a dict of index to key would suffice.

Thanks for any advice..

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Ansible has rather limited tools to work with keys in dictionaries (see this answer).

But dictsort filter can be handy sometimes, as in your case.
It converts dict into list and you can use json_query to process it.

Here's a task to fetch root key by index name:

- debug:
    msg: "key is '{{ list_with_keys | json_query(qry) }}' for index {{ item }}"
  vars:
    list_with_keys: "{{ dict1 | dictsort | to_json | from_json }}"
    qry: "[?contains(([1] | [].index),`{{ item }}`)][] | [0]"
  with_items:
    - some idx5
    - some idx3

where dict1 is taken from your example.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...