0

我有两个带有应用程序描述的数组:

source_array:
  - status: Active
    AppName": "Application 1"
    version: "0.1.1"
    metadata: ""
  - status": "Active"
    AppName: "Application 2"
    version: "0.2.2"
    metadata: "ID123"
  - status: "Active"
    AppName: "Application 3"
    version: "0.3.3"
    metadata: ""

和:

target_array:
  - status: "Active"
    AppName: "Application 1"
    version: "0.1.1"
    metadata: ""
  - status: "Active"
    AppName: "Application 2"
    version: "0.2.2"
    metadata: "ID321"
  - status: "Active",
    AppName: "Application 3"
    version: "0.3.0"
    metadata: ""

我需要根据版本字段比较这两个数组。因此,例如,期望的结果应该是:

[{
    "status": "Active",
    "AppName": "Application 3",
    "version": "0.3.0",
    "metadata": ""
}]

我尝试使用差异过滤器,但它也返回 secondf 元素 - 因为它具有不同的元数据

- name: Comparing arrays
  set_fact:
    delta: "{{ source_array | difference(target_array) }}"

我得到了不正确的结果:

[{
    "status": "Active",
    "AppName": "Application 2",
    "version": "0.2.2",
    "metadata": "ID123"
},
{
    "status": "Active",
    "AppName": "Application 3",
    "version": "0.3.3",
    "metadata": ""
},
{
    "status": "Active",
    "AppName": "Application 2",
    "version": "0.2.2",
    "metadata": "ID321"
},
{
    "status": "Active",
    "AppName": "Application 3",
    "version": "0.3.0",
    "metadata": ""
}]

任何帮助将不胜感激!

4

1 回答 1

3

这确实不是微不足道的。您没有提供太多上下文,但我怀疑您想要做的是检查应用程序是否已经或应该更新。对 ?

这是一种方法:

- hosts: localhost
  vars:
    array1:
      - status: "Active"
        AppName: "Application 1"
        version: "0.1.1"
        metadata: ""
      - status: "Active"
        AppName: "Application 2"
        version: "0.2.2"
        metadata: "ID321"
      - status: "Active"
        AppName: "Application 3"
        version: "0.3.3"
        metadata: ""
    array2:
      - status: "Active"
        AppName: "Application 1"
        version: "0.1.1"
        metadata: ""
      - status: "Active"
        AppName: "Application 2"
        version: "0.2.2"
        metadata: "ID321"
      - status: "Active"
        AppName: "Application 3"
        version: "0.3.0"
        metadata: ""

  tasks:
    - name: "Show matching pattern"
      debug:
        msg: "{{'^' + (array1|map(attribute='version'))|difference(array2|map(attribute='version'))|join('|') + '$'}}"

    - name: "Compare arrays"
      debug:
        msg: "{{ array1 | selectattr('version', 'match', '^' + (array1|map(attribute='version'))|difference(array2|map(attribute='version'))|join('|') + '$') | list }}"

它的工作原理是首先找到“较新版本”,然后根据这些筛选原始列表。但这有点脆弱的原因:

  • 它现在假设您先验地知道哪个数组包含“较新”的数据(这里所有较​​新的版本都在array1)。
  • 如果您的数组中有两个或多个具有相同版本的元素,它将保留两者,不知道选择哪个。

也许您应该考虑不同的数据结构,例如映射(dict)。请参阅current_state下面的变量:

- hosts: localhost
  vars:
    current_state:
      "Application 1":
        status: "Active"
        version: "0.1.1"
        metadata: ""
      "Application 2":
        status: "Active"
        version: "0.2.2"
        metadata: "ID321"
      "Application 3":
        status: "Active"
        version: "0.3.0"
        metadata: ""
    new_applications:
      - status: "Active"
        AppName: "Application 1"
        version: "0.1.1"
        metadata: ""
      - status: "Active"
        AppName: "Application 2"
        version: "0.2.2"
        metadata: "ID321"
      - status: "Active"
        AppName: "Application 3"
        version: "0.3.3"
        metadata: ""
      - status: "Active"
        AppName: "Application 4"
        version: "0.1.0"
        metadata: ""
  tasks:
    - name: "Different appraoch"
      debug:
         msg: "{{ item.0 }} -- {{ item.1 }} -- Should update: {{ item.1.version is version((current_state[item.0]|default({'version': '0.0.0'}))['version'], '>') }}"
      loop: "{{ new_applications|map(attribute='AppName')|zip(new_applications)|list }}"

    - name: "Build 'current_state' from a list (if not available as is)"
      # There might be a smarter way using items2dict...
      set_fact:
        dict_from_list: "{{ dict_from_list|default({})|combine({item[0]: item[1]})}}"
      loop: "{{ new_applications|map(attribute='AppName')|zip(new_applications)|list }}"

    - debug:
        var: dict_from_list

此版本修复了上述两个问题中的最后一个。如果两个数组的顺序不同,或者数组的长度不同,它也会更加健壮。

我选择忽略的第一个问题是因为,尽管您的问题让人相信array1并且array2可以互换,但我假设它们实际上不是,在给定的上下文中。

于 2019-05-31T14:18:26.060 回答