How to remove a single item from a list within a nested dictionary

The source nested dictionary is for instance the following:
vpc:
provider:

  • net_type: ‘db’
    net_ipv4_subnet: ‘10.0.0.0/16
    net_ipv6_subnet: ‘FD00::/64’
    net_id: ‘0’
    nic_ids:
  • 1111111111
  • 2222222222
  • net_type: ‘dns’
    net_ipv4_subnet: ‘10.1.0.0/16
    net_ipv6_subnet: ‘FD01::/64’
    net_id: ‘1’
    nic_ids:
  • 3333333333
  • 4444444444
  • net_type: ‘ns’
    net_ipv4_subnet: ‘10.2.0.0/16
    net_ipv6_subnet: ‘FD02::/64’
    net_id: ‘2’
    nic_ids:
  • 5555555555
  • 6666666666

We need to remove the item ''4444444444 from the list <nic_ids> located inside the dictionary matched by the key/value net_id==‘1’.

Selecting the <nic_ids> list inside the right dictionary is easy with:
vpc.provider | selectattr(‘net_id’, ‘eq’, ‘1’) | map(attribute= ‘nic_ids’), but I have no idea how to remove the item from list and build the new vpc.provider?

Any suggestion?

Here is how to get the new list:

  • name: Removing a <nic_id> from the list inside the dictionary matching the <net_id>
    vars:
    vpc:
    provider:
  • net_type: ‘db’
    net_ipv4_subnet: ‘10.0.0.0/16’
    net_ipv6_subnet: ‘FD00::/64’
    net_id: ‘0’
    nic_ids:
  • 1111111111
  • 2222222222
  • net_type: ‘dns’
    net_ipv4_subnet: ‘10.1.0.0/16’
    net_ipv6_subnet: ‘FD01::/64’
    net_id: ‘1’
    nic_ids:
  • 3333333333
  • 4444444444
  • net_type: ‘ns’
    net_ipv4_subnet: ‘10.2.0.0/16’
    net_ipv6_subnet: ‘FD02::/64’
    net_id: ‘2’
    nic_ids:
  • 5555555555
  • 6666666666
    nic_ids_:
  • 4444444444
    new_nic_ids: “{{ vpc.provider | selectattr(‘net_id’, ‘eq’, ‘1’) | map(attribute= ‘nic_ids’) | first | difference(nic_ids_) }}”
    debug:
    msg: “{{ new_nic_ids }}”

But I don’t know how to get the updated .

OK, I got it, but I’m sure there is a more elegant and simpler way to achieve the same result:

  • name: Removing a <nic_id> from the dictionary matching the <net_id>
    vars:
    vpc:
    provider:
  • net_type: ‘db’
    net_ipv4_subnet: ‘10.0.0.0/16’
    net_ipv6_subnet: ‘FD00::/64’
    net_id: ‘0’
    nic_ids:
  • 1111111111
  • 2222222222
  • net_type: ‘dns’
    net_ipv4_subnet: ‘10.1.0.0/16’
    net_ipv6_subnet: ‘FD01::/64’
    net_id: ‘1’
    nic_ids:
  • 3333333333
  • 4444444444
  • net_type: ‘ns’
    net_ipv4_subnet: ‘10.2.0.0/16’
    net_ipv6_subnet: ‘FD02::/64’
    net_id: ‘2’
    nic_ids:
  • 5555555555
  • 6666666666
    nic_ids_:
  • 4444444444
    new_nic_ids: “{{ vpc.provider | selectattr(‘net_id’, ‘eq’, ‘1’) | map(attribute= ‘nic_ids’) | first | difference(nic_ids_) }}”
    seed_vpc:
    provider:
  • net_id: ‘1’
    nic_ids: “{{ new_nic_ids }}”
    new_vpc:
    provider:
    “{{ [vpc.provider, seed_vpc.provider] | community.general.lists_mergeby(‘net_id’, recursive=True, list_merge=‘replace’) }}”
    debug:
    msg: “{{ new_vpc }}”

Put the items you want to update into a dictionary. For example,

    diff:
      '1': [4444444444]

Use Jinja to update the list

    update: |
      {% filter from_yaml %}
      {% for i in vpc.provider %}
      {% if i.net_id in diff %}
      {% set nic_ids=i.nic_ids|difference(diff[i.net_id]) %}
      - {{ i|combine({'nic_ids': nic_ids}) }}
      {% else %}
      - {{ i }}
      {% endif %}
      {% endfor %}
      {% endfilter %}

Then, create the dictionary

    new_vpc:
      provider: "{{ update }}"