根据Ansible中的键值合并两个字典列表

Merging two list of dictionaries according to a key value in Ansible

我有两个词典列表。我想根据特定的键合并它们。

这是列表 1:

"list1": [
  { "a": "b", "c": "d" },
  { "a": "e", "c": "f" }
]

这是列表 2:

"list2": [
  { "a": "e", "g": "h" },
  { "a": "b", "g": "i" }
]

所以合并后的最终词典列表应该如下所示。合并应该根据键“a”的值来完成:

"list3": [
  { "a": "b", "c": "d", "g": "i" },
  { "a": "e", "c": "f", "g": "h" }
]

对于循环、迭代等,官方文档似乎不够。我找不到完成此任务的方法。

简单的选择是reverse第二个列表combine zip列出

  list3: "{{ list1|zip(list2|reverse)|map('combine')|list }}"

给予

  list3:
    - {a: b, c: d, g: i}
    - {a: e, c: f, g: h}

下一个选项是迭代第一个列表。在循环 select 中,将第二个列表中的项目组合起来。下面的表达式给出相同的结果

    - set_fact:
        list3: "{{ list3|d([]) + [item|combine(_selection)] }}"
      loop: "{{ list1 }}"
      vars:
        _selection: "{{ list2|selectattr('a', '==', item.a)|combine }}"

如果你想

,你可以使用json_query代替selectattr
      vars:
        _selection: "{{ list2|json_query(_query)|combine }}"
        _query: '[?a==`{{ item.a }}`]'

如果可以安装合集community.general use the filter lists_mergeby。下面的表达式给出相同的结果

  list3: "{{ list1|lists_mergeby(list2, 'a') }}"

如果您无法安装该集合,请自行创建一个自定义过滤器。例如

shell> cat filter_plugins/my_lists_mergeby.py
from collections import defaultdict
from operator import itemgetter


def my_lists_mergeby(l1, l2, index):

    d = defaultdict(dict)
    for l in (l1, l2):
        for elem in l:
            if index in elem.keys():
                d[elem[index]].update(elem)
    return sorted(d.values(), key=itemgetter(index))


class FilterModule(object):

    def filters(self):
        return {
            'my_lists_mergeby': my_lists_mergeby,
        }