How to get map keys sorted by values?

I have this map

%{a: -4, b: 3, c: 0}

when I use Map.keys I get a list of fields that are not sorted by value

%{a: -4, b: 3, c: 0} |> Map.keys

[:a, :b, :c]

what I want is to sort them by value and get the following

[:b, :c, :a]

You cannot sort Map, so you need to convert it to List instead. They Map-like List with an atom as a key is called Keyword. Once you use Enum.sort_by/2 you can take the keys using Keyword.keys/1 function, for example:

%{a: -4, b: 3, c: 0}
|> Enum.to_list()
|> Enum.sort_by(&elem(&1, 1))
|> Keyword.keys()
|> dbg()

Helpful resources:

  1. Enum.sort_by/2
  2. Enum.to_list/1
  3. Kernel.dbg/1
  4. Keyword.keys/1

|> Enum.to_list() is not necessary.

Yeah, as well as dbg call - it’s more for clarity. :wink:

1 Like

I don’t think it adds clarity, it encourages an erroneous conversion of a map, which is already enumerable, to a list, which is already handled by Enum.sort_by.

@alsaraha you can also pass :desc to Enum.sort_by to sort descending as in your example:

%{a: -4, b: 3, c: 0}
|> Enum.sort_by(fn {_k, v} -> v end, :desc)
|> Keyword.keys()