Add/substract to list items - but without a loop

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

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 }}"

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') }}"

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)

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

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

This is the clear winner - thx :slight_smile: