Я предполагаю, что 1
в dd_1_a
означает, что оно должно предшествовать dd_2_a
.В этом случае вам нужно в какой-то момент выполнить сортировку, потому что порядок ключей при перечислении карты не гарантируется.
# ascending sort function
ascending = fn {k1, _}, {k2, _} -> k1 <= k2 end
%{
"dd_1_a" => 1,
"dd_1_c" => 3,
"dd_20_a" => 4,
"dd_1_b" => 2,
"dd_20_b" => 5,
"dd_20_c" => 6
}
# Parse the keys
|> Enum.map(fn {k, v} -> {Regex.run(~r/dd_(\d+)_(\w+)/, k), v} end)
# Convert into groups of 1 => [a: 1, b: 2, ...]
|> Enum.group_by(
fn {[_, k, _v1], _v2} -> String.to_integer(k) end,
fn {[_, _k, v1], v2} -> {String.to_atom(v1), v2} end
)
# Sort the keys, because the order of the keys in maps is not guaranteed
|> Enum.sort(ascending)
# Sort the internal lists too, because they were extracted from unsorted keys
|> Enum.map(fn {_, vals} -> Enum.sort(vals, ascending) end)
# Convert to tuples (skip this if you want keyword lists)
|> Enum.map(&List.to_tuple/1)
Вывод:
[{{:a, 1}, {:b, 2}, {:c, 3}}, {{:a, 4}, {:b, 5}, {:c, 6}}]
Вы упомянули, что хотели ключевое словосписки, поэтому, если вы пропустите последний шаг, вы получите:
[[a: 1, b: 2, c: 3], [a: 4, b: 5, c: 6]]