Add/substract to list items - but without a loop

190 views
Skip to first unread message

Dick Visser

unread,
Jan 21, 2022, 8:14:27 AM1/21/22
to ansible...@googlegroups.com
Hi
I have this list of ints:

selection:
  - 1
  - 4
  - 5
  - 7

I'd like to subtract 1 from each item, so that I will end up with:

selection:
  - 0
  - 3
  - 4
  - 6

I'd like to avoid adding an intermediary set_fact loop to do the math.
If I define this filter:

def subtract(number, amount=1):
    return number - amount

Then I can accomplish what I want using:

selection|map('subtract')

which is reasonably clean and understandable.

But before I add a new filter - is there any other way to achieve this?


thx


--
Dick Visser
Trust & Identity Service Operations Manager
GÉANT

Todd Lewis

unread,
Jan 21, 2022, 8:42:56 AM1/21/22
to ansible...@googlegroups.com, Dick Visser, uto...@gmail.com

I'm not proud of this, but it works:

---
- name: List subtraction
  gather_facts: no
  hosts: localhost
  vars:
    selection: [ 1, 4, 5, 7]
  tasks:
    - name: Subtract one from each selection
      debug:
        msg: "{% set result = [] -%}
              {% for v in selection -%}
              {%   set _ = result.append(v - 1) -%}
              {% endfor %}{{ result }}"
--

Todd Lewis

unread,
Jan 21, 2022, 9:11:10 AM1/21/22
to ansible...@googlegroups.com, Dick Visser, uto...@gmail.com

This also works:

---
- name: List subtraction
  gather_facts: no
  hosts: localhost
  vars:
    selection: [ 1, 4, 5, 7]
  tasks:
    - name: Subtract one from each selection
      debug:
        msg: "{{ selection| zip_longest([-1], fillvalue=-1) | map('sum') }}"

flowerysong

unread,
Jan 21, 2022, 9:16:04 AM1/21/22
to Ansible Project
This is a little weird because of the use of zip() to turn the list of integers into a list of lists, but still fairly readable IMO:

foo | zip | map('sum', start=-1)

Vladimir Botka

unread,
Jan 21, 2022, 10:01:48 AM1/21/22
to Todd Lewis, ansible...@googlegroups.com, Dick Visser
On Fri, 21 Jan 2022 09:10:52 -0500
Todd Lewis <uto...@gmail.com> wrote:

> debug: msg: "{{ selection| zip_longest([-1], fillvalue=-1) | map('sum') }}" |

You can use *product* instead of *zip*, e.g.

selection | product([-1]) | map('sum')


--
Vladimir Botka

Dick Visser

unread,
Jan 21, 2022, 2:05:50 PM1/21/22
to ansible...@googlegroups.com, Todd Lewis
This is the clear winner - thx :)

Reply all
Reply to author
Forward
0 new messages