Using ansible to merge object values with the same key in a list of dictionaries variable

Viewed 822

I have a list of dictionaries:

"users": [
    {
        "name": "bob",
        "attribute": "abc"
    },
    {
        "name": "alice",
        "attribute": "dfg"
    },
    {
        "name": "bob",
        "attribute": "rst"
    },
    {
        "name": "alice",
        "attribute": "xyz"
    }
]

I want to merge the object attributes under the same name and remove duplicates so the result would be:

"users": [
    {
        "name": "bob",
        "attribute": ["abc", "rst"]
    },
    {
        "name": "alice",
        "attribute": ["dfg", "xyz"]
    }
]

So far I've been playing with the groupby filter which produces:

"users": [
        [
            "alice",
            [
                {
                    "attribute": "dfg",
                    "name": "alice"
                },
                {
                    "attribute": "xyz",
                    "name": "alice"
                }
            ]
        ],
        [
            "bob",
            [
                {
                    "attribute": "abc",
                    "name": "bob"
                },
                {
                    "attribute": "rst",
                    "name": "bob"
                }
            ]
        ]
    ]

Now, I guess that I have to merge the object.attribute for every user.

So, how to do that..?, any help would be appreciated :)

In doing so, would it be possible to add a suffix (always the same string) to each attribute so that the result would look like this?:

    "my_users": [
        {
            "attribute": [
                "dfg_suffix",
                "xyz_suffix"
            ],
            "name": "alice"
        },
        {
            "attribute": [
                "abc_suffix",
                "rst_suffix"
            ],
            "name": "bob"
        }
    ]

I was able to figure it out so the task looks like:

    - set_fact:
        my_users:  "{{ my_users|default([]) +
                       [{'name': my_name,
                         'attribute': my_attribute}] }}"
      loop: "{{ users|groupby('name') }}"
      vars:
        my_name: "{{ item.0 }}"
        my_attribute: "{{ item.1|map(attribute='attribute')|list | map('regex_replace', '^(.*)$', '\\1_suffix') | list}}"
    - debug:
        var: my_users

which produces:

"my_users": [
        {
            "attribute": [
                "dfg_suffix", 
                "xyz_suffix"
            ], 
            "name": "alice"
        }, 
        {
            "attribute": [
                "abc_suffix", 
                "rst_suffix"
            ], 
            "name": "bob"
        }
    ]
1 Answers

The task below does the job

    - set_fact:
        my_users:  "{{ my_users|default([]) +
                       [{'name': my_name,
                         'attribute': my_attribute}] }}"
      loop: "{{ users|groupby('name') }}"
      vars:
        my_name: "{{ item.0 }}"
        my_attribute: "{{ item.1|map(attribute='attribute')|list }}"
    - debug:
        var: my_users

gives


    "my_users": [
        {
            "attribute": [
                "dfg",
                "xyz"
            ],
            "name": "alice"
        },
        {
            "attribute": [
                "abc",
                "rst"
            ],
            "name": "bob"
        }
    ]
Related