Ruby 运行长度编码失败

3
我是一名在Codewars上接受训练的新手,但我无法找到以下RLE问题中的错误所在,请看以下说明:
你的任务是编写这样一个运行长度编码。 对于给定的字符串,返回一对数组 [ (i1, s1), (i2, s2), …, (in, sn) ],使得可以通过复制sx ix次字符并连接所有这些字符串来重构原始字符串。您的运行长度编码应该是最小的,即对于所有的 i,值 si和si+1应该不同。
示例
>rle("hello world!")
# => [[1,'h'],[1,'e'],[2,'l'],[1,'o'],[1,' '],[1,'w'],[1,'o'],[1,'r'],[1,'l'],[1,'d'],[1,'!']]

>rle("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbb")
# => [[34,'a'], [3,'b']]

这是我的代码:

def rle(str)
  result=[[]]
  str.to_s.split.each do |word| #"Hello World"->["Hello","World!"]-->"Hello", "World!"
    new_word_count=[[]]
    word.each_char do |char| #"H","e","l"...
      new_char=true
      new_word_count.map! do |find|
        if find[1]==char
        find[0]+=1
        new_char=false
        break
        end
      end
      if new_char==true
        new_word_count<<[1,'char']
      end
    end
    result+=new_word_count
  end
  result
end

我收到了这个错误信息:
`block (3 levels) in rle': undefined method `[]' for nil:NilClass (NoMethodError)
from `map!'
from  `block (2 levels) in rle'
from  `each_char'
from  `block in rle'
from  `each'
from  `rle'
from  `
'

运行长度编码(RLE)是一种非常简单的数据压缩形式,其中数据的连续序列(即,相同的数据值在许多连续的数据元素中出现的序列)被存储为单个数据值和计数,而不是原始的连续序列。维基百科


你是否误用了 map!map 的目的是将数组的每个元素转换为另一个具有相同元素数量的数组,这些元素由提供给 map 的块确定。而 map! 则直接替换原始数组中的每个元素。 - lurker
@lurker,我不是很确定。我认为如果我想就地修改数组(仅在需要时增加该字符的计数),我必须使用map!。谢谢您的快速回答 :) - Guillermo García Serrano
你在 map 块中间使用了 break,这是一个很好的迹象,说明你没有正确使用它。看起来更像是你试图使用它来循环遍历数组元素以修改不同的变量,这应该使用类似于 each 的东西来完成。 - lurker
@lurker 哦,我现在明白了。再次感谢你的帮助。 - Guillermo García Serrano
为什么需要先将原始字符串拆分为以空格分隔的单词?根据您想要获得的示例结果,似乎单词拆分并不相关。您在RLE中计算空格的数量就像其他字符一样。 - lurker
是的,@lurker,你说得对。我没有完全理解说明书,做得不好。我很高兴这不是大学考试或者什么的,否则后果不堪设想。 - Guillermo García Serrano
2个回答

1
def rle s
  s.each_char.inject([]) do |memo, c| 
     memo.last && c == memo.last.last ? memo.last[0] += 1 : memo << [1, c]
     memo
  end
end

在这里我们检查最后一个字符 (memo.last.last),如果它与当前字符相同,则增加计数器。否则,我们将新数组添加到列表中。

谢谢@mudasobwa的快速回答!我需要考虑一下那段代码 :) 无论如何,你能找到我的错误在哪里吗?尽管它不是最聪明或最有效的代码。 - Guillermo García Serrano
我不能用几个词来解释: 代码中包含许多错误。你甚至在解决其他的任务: 你试图查找已存在的元素,而任务明确指出你只需要检查最后一个(请参见你所期望的输出中的l:它出现了两次)。 - Aleksei Matiushkin
好的@mudasobwa。再次感谢您的时间 :) - Guillermo García Serrano

-1

运行长度编码

str = wwwwaaadexxxxxx # After encoding w4a3d1e1x6
h = {} 
str.split("").map{|e| h[e].nil? ? h[e] = 1 : h[e] +=1}
h.to_a.flatten.join # w4a3d1e1x6

它没有考虑账户中所有情况的可能性。尝试像这样使用 "wwwawwwwwbwwww",之后你将无法正确解码它。 - konung

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接