Suppose I have a map in Elixir:
m = %{"a"=>1, "b"=>2, "c" => 3}
If I call Map.values(m)
, am I guaranteed that the return value will always be [1, 2, 3]
in that order and not say, [3, 1, 2]
?
This is one thing I am not clear on from the docs. After some preliminary testing, I think it is.
The implementation of Maps in Elixir and Erlang has some confusing properties. For small values of entries it is a sorted key list, and thus appears to have the properties you see in simple experiments.
Above a certain number of entries (32 I think), the implementation switches to Hash Array Mapped Trie and all the properties you see disappear. You can not depend on the order of either the keys or the values of a map in the general case. See
https://en.wikipedia.org/wiki/Hash_array_mapped_trie
for an explaination of the underlying structure of Map.
iex(7)> 1..33 |> Enum.reduce(%{}, fn(x, acc) -> Map.put(acc,x,x) end )
%{11 => 11, 26 => 26, 15 => 15, 20 => 20, 17 => 17, 25 => 25, 13 => 13, 8 => 8, 7 => 7, 1 => 1, 32 => 32, 3 => 3, 6 => 6, 2 => 2, 33 => 33, 10 => 10, 9 => 9, 19 => 19, 14 => 14, 5 => 5, 18 => 18, 31 => 31, 22 => 22, 29 => 29, 21 => 21, 27 => 27, 24 => 24, 30 => 30, 23 => 23, 28 => 28, 16 => 16, 4 => 4, 12 => 12}
iex(8)> Map.keys(v(7)) [11, 26, 15, 20, 17, 25, 13, 8, 7, 1, 32, 3, 6, 2, 33, 10, 9, 19, 14, 5, 18, 31, 22, 29, 21, 27, 24, 30, 23, 28, 16, 4, 12]
iex(9)> Map.values(v(7)) [11, 26, 15, 20, 17, 25, 13, 8, 7, 1, 32, 3, 6, 2, 33, 10, 9, 19, 14, 5, 18, 31, 22, 29, 21, 27, 24, 30, 23, 28, 16, 4, 12]