简体   繁体   中英

How to change all the values in an Elixir map

I see that there's an update in the Dict module, but what about an update_all method that changes all values?

I tried doing this with Enum.map but the type changed:

iex(6)> Enum.map(%{:a => 2}, fn {k, v} -> {k, v + 1} end)
[a: 3]

You could pipe to Enum.into(%{}) or use a for comprehension, ie:

iex> for {k, v} <- %{a: 1, b: 2}, into: %{}, do: {k, v + 1}
%{a: 2, b: 3}

You can also do:

iex> Map.new(%{:a => 2}, fn {k, v} -> {k, v + 1} end)
%{:a => 3}

But feel like there should be something in the standard library to make this easier ( Map.??(%{:a => 2}, &(&1 + 1)) ).

Here's one idea:

def update_map map, [head|tail], func do
    update_map(
        Dict.update(map, head, :unknown, func),
        tail,
        func
    )
end


def update_map map, [], _ do
    map
end

Then to call it:

iex(1)> d = %{:a => 1, :b => 2, :c => 3}
%{a: 1, b: 2, c: 3}
iex(2)> update_map(d, Dict.keys(d), fn v -> v + 1 end)
%{a: 2, b: 3, c: 4}

Let me add Enum.into into the mix

headers
|> Enum.group_by(fn {k, _v} -> k end, fn {_k, v} -> v end)
|> Enum.into(%{}, fn {k, v} -> {k, Enum.join(v, ", ")} end)

This turns:

[{"cookie", "a"}, {"cookie", "b"}] into %{"cookie", "a, b"}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM