统计ansible中列表中每个唯一元素的出现次数

问题描述 投票:0回答:2

如何计算列表中每个项目重复了多少次?

    ok: [] => {
        "list": [
            "5.8.3",
            "5.8.4",
            "5.8.4",
            "5.9.2",
            "5.9.2",
            "5.9.2"
        ]
    }
    

我想打印这样的东西:

    ok: [] => {
        "list_counter": [
            "5.8.3": 1
            "5.8.4": 2
            "5.9.2": 3
        ]
    }

我尝试过类似的事情,但没有成功

    - set_fact:
        list_counter: '{{ item : 1 + item.get(unique_int[item],0) }}'
      loop: "{{ list }}" 
list count ansible
2个回答
4
投票
list_counter: "{{ list|community.general.counter }}"

给出了预期的结果

list_counter:
  5.8.3: 1
  5.8.4: 2
  5.9.2: 3

  • 如果您无法安装该集合,请获取代码并创建自定义过滤器插件
shell> cat filter_plugins/my_counter.py 
# -*- coding: utf-8 -*-
# Copyright (c) 2021, Remy Keil <[email protected]>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

from ansible.errors import AnsibleFilterError
from ansible.module_utils.common._collections_compat import Sequence
from collections import Counter


def my_counter(sequence):
    ''' Count elements in a sequence. Returns dict with count result. '''
    if not isinstance(sequence, Sequence):
        raise AnsibleFilterError('Argument for community.general.counter must be a sequence (string or list). %s is %s' %
                                 (sequence, type(sequence)))

    try:
        result = dict(Counter(sequence))
    except TypeError as e:
        raise AnsibleFilterError(
            "community.general.counter needs a sequence with hashable elements (int, float or str) - %s" % (e)
        )
    return result


class FilterModule(object):
    ''' Ansible counter jinja2 filters '''

    def filters(self):
        filters = {
            'my_counter': my_counter,
        }

        return filters

使用它

list_counter: "{{ list|my_counter }}"

  • 如果您不想使用集合或编写自定义过滤器,下面的声明会给出相同的结果
list_counter: "{{ dict(data | unique |
                       zip(data |
                           json_query('[].{key:@, value: `1`}')|
                           groupby('key') |
                           map(attribute=1) |
                           map('map', attribute='value') |
                           map('sum') | list)) }}"

2
投票

如果您不想安装集合或编写自定义过滤器,您可以使用

combine
过滤器来完成此操作:

- hosts: localhost
  gather_facts: false
  vars:
    data: [
      "5.8.3",
      "5.8.4",
      "5.8.4",
      "5.9.2",
      "5.9.2",
      "5.9.2"
    ]

  tasks:
    - set_fact:
        result_list: "{{ result_list | combine({item: result_list[item]|default(0) + 1}) }}"
      loop: "{{ data }}"
      vars:
        result_list: {}

    - debug:
        msg: "{{ result_list }}"

上述剧本输出:


PLAY [localhost] ***************************************************************

TASK [set_fact] ****************************************************************
ok: [localhost] => (item=5.8.3)
ok: [localhost] => (item=5.8.4)
ok: [localhost] => (item=5.8.4)
ok: [localhost] => (item=5.9.2)
ok: [localhost] => (item=5.9.2)
ok: [localhost] => (item=5.9.2)

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": {
        "5.8.3": 1,
        "5.8.4": 2,
        "5.9.2": 3
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
© www.soinside.com 2019 - 2024. All rights reserved.