我认为,有一些更容易理解的方法可能适合您。使用正则表达式:
Regex.scan(~r/a/, str) |> Enum.count
或将字符串分成其unicode字符,然后依靠:
str |> String.graphemes |> Enum.count(fn(c) -> c == "a" end)
这些不是非常有效的方法,但是对于仅500个字符长的(相对较小!)字符串,性能影响应该可以忽略不计。
如果您需要一种更有效的方法,一个好的选择通常是使用递归进行迭代,然后手动计算发生次数。尽管此方法非常冗长,但性能要好得多。
defmodule Recursive do
def count(str, <<c::utf8>>) do
do_count(str, c, 0)
end
defp do_count(<<>>, _, acc) do
acc
end
defp do_count(<<c::utf8, rest::binary>>, c, acc) do
do_count(rest, c, acc + 1)
end
defp do_count(<<_::utf8, rest::binary>>, c, acc) do
do_count(rest, c, acc)
end
end
最后,这是到目前为止使用基准测试的基准。我还提供了@DeboraMartins的“split length”解决方案,该解决方案在小字符串方面的性能优于上述所有解决方案。对于较大的字符串,与递归方法的区别可以忽略不计。
# 500 Characters
split length 500000 5.90 µs/op
recursive 100000 10.63 µs/op
regex count 100000 24.35 µs/op
graphemes count 10000 118.29 µs/op
# 500.000 Characters
split length 100 11150.59 µs/op
recursive 100 12002.20 µs/op
regex count 100 25313.40 µs/op
graphemes count 10 218846.20 µs/op