У меня есть список таких слов:
list_of_dicts:
- name: Item1
- name: Item2
type: special
- name: Item3
- name: Item4
type: small
Как видите, не все предметы имеют type
атрибут. Контекст: если нет type
установлен, это означает, что элемент имеет тип по умолчанию.
Я хотел бы выбрать все предметы, НЕ относящиеся к типу special
.
Я пробовал это: list_of_dicts | rejectattr('type', 'equalto', 'special')
К сожалению, это не удается AnsibleUndefinedVariable: 'dict object' has no attribute 'type'
ошибка, потому что некоторые элементы не имеют типа.
Как лучше решить эту проблему?
Вы должны использовать rejectattr
отклонять предметы, которые type
undefined и используйте selectattr
для выбора элементов, которые equalto
специальный.
{{ list_of_dicts | rejectattr("type", "undefined") | selectattr("type", "equalto", "special") | list }}
редактировать:
Как насчет объединения двух списков, как показано ниже? Не знаю, лучший ли это способ, но он работает.
{{ list_of_dicts | selectattr("type", "undefined") | list }} + {{ list_of_dicts | rejectattr("type", "undefined") | rejectattr("type", "equalto", "special") | list}}
Изменить: на самом деле я не обратил достаточно внимания на последнее изменение существующего ответа от @ranjandas и следующие комментарии. Мое первое решение почти похоже. Думаю, вас больше интересует второй.
Вот 2 разных способа выполнения ваших требований.
Первое решение использует только доступные по умолчанию фильтры: rejectattr
вы уже упомянули и его аналог selectattr
. Идея состоит в том, чтобы добавить два списка. Первый делается путем выбора всех диктовок, не имеющих type
атрибут. Второй делается выбором dict, имеющего type
атрибут и отклонение тех, где он равен special
.
Для второго решения я использовал json_query
фильтр что требует pip install jmespath
на контроллере. Как видите ниже, он намного компактнее.
Выбор за вами !
Демо-сценарий:
---
- name: Show not so special items
hosts: localhost
gather_facts: false
vars:
list_of_dicts:
- name: Item1
- name: Item2
type: special
- name: Item3
- name: Item4
type: small
tasks:
- name: Use select/rejectattr
debug:
msg: >-
{{
(list_of_dicts | selectattr('type', 'undefined') | list)
+
(list_of_dicts | selectattr('type', 'defined') | rejectattr('type', 'eq', 'special') | list)
}}
- name: Use json_query
vars:
query: "[?type != 'special']"
debug:
msg: "{{ list_of_dicts | json_query(query) | list }}"
Который дает:
PLAY [Show not so special items] **********************************************************************************************************************************************************************************
TASK [Use select/rejectattr] **************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"name": "Item1"
},
{
"name": "Item3"
},
{
"name": "Item4",
"type": "small"
}
]
}
TASK [Use json_query] *********************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"name": "Item1"
},
{
"name": "Item3"
},
{
"name": "Item4",
"type": "small"
}
]
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0