远非完美,但有效。
这对我不起作用:
我的.exs:
defmodule Stuff do
def numeric_for_sort(string) do
letters = ["a", "ą", "b", "c", "ć", "d", "e", "ę", "f", "g", "h", "i", "j", "k", "l", "ł",
"m", "n", "ń", "o", "ó", "p", "q", "r", "s", "ś", "t", "u", "w", "y", "z", "ź", "ż"]
String.graphemes(string)
|> Enum.map(fn(x) -> Enum.find_index(letters, fn(y) -> x == y end) end)
end
end
^C~/elixir_programs$ iex my.exs
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Enum.sort(["lubelskie", "mazowieckie", "zachodniopomorskie", "łódzkie"], &(Stuff.numeric_for_sort(&1["name"]) <= Stuff.numeric_for_sort(&2["name"])))
** (FunctionClauseError) no function clause matching in Access.get/3
The following arguments were given to Access.get/3:
# 1
"lubelskie"
# 2
"name"
# 3
nil
(elixir) lib/access.ex:306: Access.get/3
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(stdlib) erl_eval.erl:878: :erl_eval.expr_list/6
(stdlib) erl_eval.erl:404: :erl_eval.expr/5
(stdlib) erl_eval.erl:469: :erl_eval.expr/5
(stdlib) lists.erl:969: :lists.sort/2
(FunctionClauseError) no function clause matching in Access.get/3`.
而且,我认为您不想为字母使用列表,因为您必须不断遍历列表来搜索字母。这就是地图的用途。 (编辑:嗯,我知道什么:small maps 是有序列表,其中地图有
letters = ["a", "ą", "b", "c", "ć", "d", "e", "ę", "f", "g", "h", "i", "j", "k", "l", "ł",
"m", "n", "ń", "o", "ó", "p", "q", "r", "s", "ś", "t", "u", "w", "y", "z", "ź", "ż"]
letter_rank = Map.new Enum.with_index letters
String.graphemes(string)
|> Enum.map(fn(x) -> letter_rank[x] end)
然后:
names = ["lubelskie", "łódzkie", "mazowieckie", "zachodniopomorskie"]
["lubelskie", "łódzkie", "mazowieckie", "zachodniopomorskie"]
iex(2)> Enum.sort_by names, &Stuff.numeric_for_sort/1
["lubelskie", "łódzkie", "mazowieckie", "zachodniopomorskie"]
iex(3)>
根据Enum.sort_by/3 文档:
sort_by/3 与 sort/2 的不同之处在于它只计算可枚举中每个元素的比较值一次,而不是
每次比较中的每个元素一次。如果相同的功能是
在两个元素上都被调用,使用起来也更紧凑
sort_by/3.
排序时会进行很多比较,对于排序算法进行的每次比较,一遍又一遍地计算每个名称的数字列表显然并不理想。
请注意,即使这一行:
Enum.sort_by names, &Stuff.numeric_for_sort/1
看起来它正在调用 sort_by/2,它实际上是使用默认的第三个参数 &<=/2 调用 sort_by/3。