# Update matching list items with Access.filter/1

Use `Access.filter/1` to update only the list elements that match a predicate, without mapping and rebuilding the surrounding structure yourself.

```elixir
order = %{
  items: [
    %{sku: "A", status: :pending, cents: 1_000},
    %{sku: "B", status: :paid, cents: 2_000},
    %{sku: "C", status: :pending, cents: 500}
  ]
}

update_in(
  order,
  [:items, Access.filter(&(&1.status == :pending)), :cents],
  &div(&1 * 90, 100)
)

# => %{
#      items: [
#        %{sku: "A", status: :pending, cents: 900},
#        %{sku: "B", status: :paid, cents: 2000},
#        %{sku: "C", status: :pending, cents: 450}
#      ]
#    }
```

The predicate runs against every item in the list. Each match continues through the rest of the access path, so `:cents` is updated only for pending items. Non-matching elements and the enclosing map keep their original shape.

The same accessor works with `get_in/2`, `get_and_update_in/3`, and `pop_in/2`. If nothing matches, the structure is returned unchanged.

`Access.filter/1` expects the value at that point in the path to be a list. It raises when it encounters another data type, so make optional or mixed-shape data explicit before traversing it.

[Access.filter/1 docs](https://hexdocs.pm/elixir/Access.html#filter/1)


---

Created by: almirsarajcic
Date: September 04, 2026
URL: https://elixirdrops.net/d/tUruhd8q
