对elixir中的重复字母进行分组或计数
我在用长生不老药数一数字符串上的重复字母。 我确实尝试过一些尝试,但直到现在都没有成功 让我们以这个字符串为例:对elixir中的重复字母进行分组或计数,elixir,Elixir,我在用长生不老药数一数字符串上的重复字母。 我确实尝试过一些尝试,但直到现在都没有成功 让我们以这个字符串为例:“AAABBAAC” 所需输出为“3A2B2A1C” 将此字符串转换为列表,我可以计算每个字母,结果是“5A2B1C”,但我必须按照顺序进行计数 这是我正在做的代码: string |> String.graphemes |> Enum.reduce([], fn(letter, acc) -> Keyword.update(acc, letter, 1, &
“AAABBAAC”
所需输出为“3A2B2A1C”
将此字符串转换为列表
,我可以计算每个字母,结果是“5A2B1C”
,但我必须按照顺序进行计数
这是我正在做的代码:
string
|> String.graphemes
|> Enum.reduce([], fn(letter, acc) -> Keyword.update(acc, letter, 1, &(&1 + 1)) end)
但是,在我的测试中,我试图生成一个列表,像这样[“AAA”,“BB”,“AA”,“C”]
,这样我就可以轻松地用String.lenght进行计数
看起来像是使用了Enum.chunk\u by
我正在接近解决方案
有没有办法产生这样的结果?如果使用递归方法实现,您可以轻松跟踪最后出现的字符及其当前计数,以及保存结果的累加器。如果当前字符等于最后一个字符,则只需增加计数。如果两者不同,则将最后一个字符及其计数添加到累加器中,然后继续下一个字符,直到字符串为空。最后,对最终值进行编码并返回结果
defmodule RunLengthEncoding do
# public interface, take first char and remember it as the current value
def encode(<<char::utf8, rest::binary>>) do
do_encode(rest, char, 1, "")
end
# current == last, increase the count and proceed
defp do_encode(<<char::utf8, rest::binary>>, char, count, acc) do
do_encode(rest, char, count + 1, acc)
end
# current != last, reset count, encode previous values and proceed
defp do_encode(<<char::utf8, rest::binary>>, last, count, acc) do
do_encode(rest, char, 1, acc <> to_string(count) <> <<last::utf8>>)
end
# input empty, encode final values and return
defp do_encode("", last, count, acc) do
acc <> to_string(count) <> <<last::utf8>>
end
end
defmodule运行代码
#公共接口,获取第一个字符并将其作为当前值记住
def encode()do
是否进行编码(rest,字符,1,“”)
结束
#当前==最后,增加计数并继续
defp do_编码(,字符,计数,acc)do
do_编码(剩余、字符、计数+1、acc)
结束
#电流!=最后,重置计数,编码之前的值并继续
defp do_编码(,最后,计数,acc)do
do_编码(rest、char、1,根据_字符串(计数))
结束
#输入空,编码最终值并返回
defp do_encode(“”,last,count,acc)do
根据_字符串(计数)
结束
结束
根据,我确实是这样解决的:
string
|> String.graphemes
|> Enum.chunk_by(fn arg -> arg end)
|> Enum.map(fn arg -> to_string(arg) end)
|> Enum.reduce("", fn(arg, acc) -> acc <> to_string(String.length(arg)) <> String.first(arg) end)
Enum.chunk\u by(fn arg->arg end)
将每个重复的字母分组到新列表中:
[["A", "A", "A"], ["B", "B"], ["A", "A"], ["C"]]
Enum.map(fn arg->to_string(arg)end)
将其重新组合在一起:
["AAA", "BB", "AA", "C"]
Enum.reduce(“,fn(arg,acc)->acc to_string(string.length(arg))string.first(arg)end)
最后将计数(string.length
)和第一个字母(string.first
)连接到初始累加器(”
):
你可以像下面这样做,也可以引导我们了解你的逻辑。到目前为止你是怎么做到的?你在做这个吗?这里有一个很好的递归实现:@OnorioCatenacci,不知道frostmage,但这是一个练习。我没有投反对票,但这里有一个可能的原因:纯粹的代码编写请求与堆栈溢出无关——我们希望这里的问题与特定的编程问题有关——但我们很乐意帮助您自己编写!告诉我们,你被困在哪里了。这也将帮助我们更好地回答您的问题。这是一个很好的答案,谢谢。但是,我能够使用更少的代码进行编码,从而提高可读性。我不确定您的解决方案是否更具可读性@Hostert。代码行数越少,可读性就越高。单字符变量比长名称短,但它们的可读性几乎没有提高。看起来是个不错的解决方案,但您正在构建许多中间列表。这意味着这将比我的方法执行得更差,但如果您只处理小字符串,它将工作得很好;-)@PatrickOscity感谢您的反馈。是的,这只是一个关于exercism.io的小练习。性能之类的东西没什么大不了的。由于我对长生不老药完全是个新手,我想我将开始在更高的层次上处理性能问题。
["AAA", "BB", "AA", "C"]
"3A2B2A1C"