如何比较两个以上的列表在 Ansible 的相同索引中具有相同的值?
How to compare more than two lists have the same values in same indexes in Ansible?
我想比较 2 个以上的列表,看看它们在相同索引中是否具有相同的值。
我之前有关于如何交替多个列表中的值的问题。
基于此,我需要比较每个值并在值不相同时停止。 (可能有更好的解决办法,欢迎补充)
---
- name: data test
hosts: localhost
vars:
data_1: [True, False, True]
data_2: [False, True, True]
tasks:
- name: combine
set_fact:
comp_data: "{{ comp_data | default([]) + [item] }}"
loop:
- "{{ data_1 }}"
- "{{ data_2 }}"
- name: list all comp_data
debug:
msg: "{{ comp_data }}"
- name: zip
set_fact:
zip_data: "{{ lookup('together', *comp_data) }}"
- name: list all zip comp_data
debug:
msg: "{{ zip_data }}"
- name: check each element are identical
assert:
that:
- "{{ item | unique | length == 1 }}"
msg: |
"Data is not identical"
"{{ item }}"
loop: "{{ zip_data }}"
输出:
TASK [check each element are identical] *************************************************************************************************************************************************
failed: [localhost] (item=[True, False]) => {
"ansible_loop_var": "item",
"assertion": false,
"changed": false,
"evaluated_to": false,
"item": [
true,
false
]
}
MSG:
"Data is not identical"
"[True, False]"
failed: [localhost] (item=[False, True]) => {
"ansible_loop_var": "item",
"assertion": false,
"changed": false,
"evaluated_to": false,
"item": [
false,
true
]
}
MSG:
"Data is not identical"
"[False, True]"
ok: [localhost] => (item=[True, True]) => {
"ansible_loop_var": "item",
"changed": false,
"item": [
true,
true
]
}
MSG:
All assertions passed
最后,它应该一看到不相同就停止,但它会迭代到最后一个列表。
知道如何立即停止以及比较列表的更好方法吗?
谢谢,
问:“一看到 non-identical 项就停止。”
A:查找索引和 slice 列表。例如,给定数据
data_1: [True, False, True]
data_2: [False, True, True]
找到列表开始不同的索引
data_diff: "{{ data_1|zip(data_2)|
map('unique')|
map('length')|
map('log', 100)|map('round', 0, method='ceil')|map('int')|
list }}"
data_stop_index: |-
{% if 1 in data_diff %}{{ data_diff.index(1) }}
{% else %}{{ data_diff|length }}
{% endif %}
给予
data_diff: [1, 1, 0]
data_stop_index: 0
然后,迭代
- debug:
msg: "{{ item|to_yaml }}"
with_together:
- "{{ data_1[:data_stop_index|int] }}"
- "{{ data_2[:data_stop_index|int] }}"
没有给出结果,因为前几项不同
当您更改数据时
data_1: [True, False, True]
data_2: [True, True, True]
以上任务将显示第一个项目
msg: |-
[true, true]
可以修改代码以处理更多列表。例如,给定数据
data_1: [A, B, C]
data_2: [A, X, C]
data_3: [A, B, C]
zip 和 flatten 最多 100 个列表(如果需要更多,请增加对数底数)
data_diff: "{{ data_1|zip(data_2)|zip(data_3)|
map('flatten')|
map('unique')|
map('length')|
map('log', 100)|map('round', 0, method='ceil')|map('int')|
list }}"
data_stop_index: |-
{% if 1 in data_diff %}{{ data_diff.index(1) }}
{% else %}{{ data_diff|length }}
{% endif %}
给予
data_diff: [0, 1, 0]
data_stop_index: 1
然后,对所有列表进行切片和迭代
- debug:
msg: "{{ item|to_yaml }}"
with_together:
- "{{ data_1[:data_stop_index|int] }}"
- "{{ data_2[:data_stop_index|int] }}"
- "{{ data_3[:data_stop_index|int] }}"
给出第一个项目
msg: |-
[A, A, A]
可以选择创建自定义过滤器来比较列表中的项目
shell> cat filter_plugins/bool.py
def bool_gt(a, b):
return (a > b)
class FilterModule(object):
''' Ansible filters for operating on Boolean '''
def filters(self):
return {
'bool_gt': bool_gt,
}
然后,使用它代替笨拙的 built-in 过滤器管道 (log, round, int)
data_diff: "{{ data_1|zip(data_2)|zip(data_3)|
map('flatten')|
map('unique')|
map('length')|
map('bool_gt', 1)|
list }}"
并拟合指数的计算
data_stop_index: |-
{% if true in data_diff %}
{{ data_diff.index(true) }}
{% else %}
{{ data_diff|length }}
{% endif %}
我想比较 2 个以上的列表,看看它们在相同索引中是否具有相同的值。
我之前有关于如何交替多个列表中的值的问题。
---
- name: data test
hosts: localhost
vars:
data_1: [True, False, True]
data_2: [False, True, True]
tasks:
- name: combine
set_fact:
comp_data: "{{ comp_data | default([]) + [item] }}"
loop:
- "{{ data_1 }}"
- "{{ data_2 }}"
- name: list all comp_data
debug:
msg: "{{ comp_data }}"
- name: zip
set_fact:
zip_data: "{{ lookup('together', *comp_data) }}"
- name: list all zip comp_data
debug:
msg: "{{ zip_data }}"
- name: check each element are identical
assert:
that:
- "{{ item | unique | length == 1 }}"
msg: |
"Data is not identical"
"{{ item }}"
loop: "{{ zip_data }}"
输出:
TASK [check each element are identical] *************************************************************************************************************************************************
failed: [localhost] (item=[True, False]) => {
"ansible_loop_var": "item",
"assertion": false,
"changed": false,
"evaluated_to": false,
"item": [
true,
false
]
}
MSG:
"Data is not identical"
"[True, False]"
failed: [localhost] (item=[False, True]) => {
"ansible_loop_var": "item",
"assertion": false,
"changed": false,
"evaluated_to": false,
"item": [
false,
true
]
}
MSG:
"Data is not identical"
"[False, True]"
ok: [localhost] => (item=[True, True]) => {
"ansible_loop_var": "item",
"changed": false,
"item": [
true,
true
]
}
MSG:
All assertions passed
最后,它应该一看到不相同就停止,但它会迭代到最后一个列表。
知道如何立即停止以及比较列表的更好方法吗?
谢谢,
问:“一看到 non-identical 项就停止。”
A:查找索引和 slice 列表。例如,给定数据
data_1: [True, False, True]
data_2: [False, True, True]
找到列表开始不同的索引
data_diff: "{{ data_1|zip(data_2)|
map('unique')|
map('length')|
map('log', 100)|map('round', 0, method='ceil')|map('int')|
list }}"
data_stop_index: |-
{% if 1 in data_diff %}{{ data_diff.index(1) }}
{% else %}{{ data_diff|length }}
{% endif %}
给予
data_diff: [1, 1, 0]
data_stop_index: 0
然后,迭代
- debug:
msg: "{{ item|to_yaml }}"
with_together:
- "{{ data_1[:data_stop_index|int] }}"
- "{{ data_2[:data_stop_index|int] }}"
没有给出结果,因为前几项不同
当您更改数据时
data_1: [True, False, True]
data_2: [True, True, True]
以上任务将显示第一个项目
msg: |-
[true, true]
可以修改代码以处理更多列表。例如,给定数据
data_1: [A, B, C]
data_2: [A, X, C]
data_3: [A, B, C]
zip 和 flatten 最多 100 个列表(如果需要更多,请增加对数底数)
data_diff: "{{ data_1|zip(data_2)|zip(data_3)|
map('flatten')|
map('unique')|
map('length')|
map('log', 100)|map('round', 0, method='ceil')|map('int')|
list }}"
data_stop_index: |-
{% if 1 in data_diff %}{{ data_diff.index(1) }}
{% else %}{{ data_diff|length }}
{% endif %}
给予
data_diff: [0, 1, 0]
data_stop_index: 1
然后,对所有列表进行切片和迭代
- debug:
msg: "{{ item|to_yaml }}"
with_together:
- "{{ data_1[:data_stop_index|int] }}"
- "{{ data_2[:data_stop_index|int] }}"
- "{{ data_3[:data_stop_index|int] }}"
给出第一个项目
msg: |-
[A, A, A]
可以选择创建自定义过滤器来比较列表中的项目
shell> cat filter_plugins/bool.py
def bool_gt(a, b):
return (a > b)
class FilterModule(object):
''' Ansible filters for operating on Boolean '''
def filters(self):
return {
'bool_gt': bool_gt,
}
然后,使用它代替笨拙的 built-in 过滤器管道 (log, round, int)
data_diff: "{{ data_1|zip(data_2)|zip(data_3)|
map('flatten')|
map('unique')|
map('length')|
map('bool_gt', 1)|
list }}"
并拟合指数的计算
data_stop_index: |-
{% if true in data_diff %}
{{ data_diff.index(true) }}
{% else %}
{{ data_diff|length }}
{% endif %}