# Convert multiple map values conditionally

**URL:** <https://forum.elixirforum.com/t/convert-multiple-map-values-conditionally/31606>\
**Category:** Questions\
**Tags:** maps, pipe-operator\
**Created:** [May 18, 2020, 8:56am UTC](https://forum.elixirforum.com/t/convert-multiple-map-values-conditionally/31606 "2020-05-18T08:56:10Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![kip](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/kip/32/1440_2.png) [@kip](https://forum.elixirforum.com/u/kip)\
**Post date:** [May 18, 2020, 9:53am UTC](https://forum.elixirforum.com/t/convert-multiple-map-values-conditionally/31606/3 "2020-05-18T09:53:10Z")

</div>

I have a function called [deep\_map](https://github.com/elixir-cldr/cldr_utils/blob/master/lib/cldr/utils/map.ex#L17-L171) that I use in several different projects to simplify certain classes of map operations. On top of that I have other functions like [atomize\_keys/3](https://github.com/elixir-cldr/cldr_utils/blob/master/lib/cldr/utils/map.ex#L17-L171) and so on. It might be useful (or it might be not 🙂 )

### Summary

Recursively traverse a map and invoke a function  
that transforms the map for each key/value pair.

### Arguments

- `map` is any `t:map/0`
- `function` is a `1-arity` function or function reference that  
is called for each key/value pair of the provided map. It can  
also be a 2-tuple of the form `{key_function, value_function}`
  - In the case where `function` is a single function it will be  
called with the 2-tuple argument `{key, value}`
  - In the case where function is of the form `{key_function, value_function}`  
the `key_function` will be called with the argument `key` and the value  
function will be called with the argument `value`

- `options` is a keyword list of options. The default is `[]`

### Options

- `:level` indicates the starting (and optionally ending) levels of  
the map at which the `function` is executed. This can  
be an integer representing one `level` or a range  
indicating a range of levels. The default is `1..#{@max_level}`
- `:only` is a term or list of terms or a `check function`. If it is a term  
or list of terms, the `function` is only called if the `key` of the  
map is equal to the term or in the list of terms. If `:only` is a  
`check function` then the `check function` is passed the `{k, v}` of  
the current branch in the `map`. It is expected to return a `truthy`  
value that if `true` signals that the argument `function` will be executed.
- `:except` is a term or list of terms or a `check function`. If it is a term  
or list of terms, the `function` is only called if the `key` of the  
map is not equal to the term or not in the list of terms. If `:except` is a  
`check function` then the `check function` is passed the `{k, v}` of  
the current branch in the `map`. It is expected to return a `truthy`  
value that if `true` signals that the argument `function` will not be executed.

### Notes

If both the options `:only` and `:except` are provided then the `function`  
is called only when a `term` meets both criteria.

### Returns

- The `map` transformed by the recursive application of  
`function`

### Examples

```
  iex> map = %{a: :a, b: %{c: :c}}
  iex> fun = fn
  ...> {k, v} when is_atom(k) -> {Atom.to_string(k), v}
  ...> other -> other
  ...> end
  iex> Cldr.Map.deep_map map, fun
  %{"a" => :a, "b" => %{"c" => :c}}
  iex> map = %{a: :a, b: %{c: :c}}
  iex> Cldr.Map.deep_map map, fun, only: :c
  %{a: :a, b: %{"c" => :c}}
  iex> Cldr.Map.deep_map map, fun, except: [:a, :b]
  %{a: :a, b: %{"c" => :c}}
  iex> Cldr.Map.deep_map map, fun, level: 2
  %{a: :a, b: %{"c" => :c}}

```

---

_[View the full topic](https://forum.elixirforum.com/t/convert-multiple-map-values-conditionally/31606)._
