>我正在尝试循环访问一个字符串:
statement = "The Game of Throne Rocks!"
用字母作为我的哈希值的键。我的键的值将是字母在我的字符串中出现的次数。
我通过堆栈溢出找到了这段代码:
statement.each_char do |char|
next if char == " "
result[char] = 0 unless statement.include?(char)
result[char] += 1
end
它有效,我试图重写它以达到我的理解。我下面的代码不起作用:
result = {}
statement.each_char do |char|
if char == ' '
next
elsif result.include?(char)
result[char] += 1
else
result[char] = 0
end
end
请帮忙。
原始代码示例无条件执行 result[char] += 1
,而您的代码示例仅在第二次看到字母时执行此操作。
也可以通过将哈希条目初始化为 1 来修复代码。
每次输入一个新字符时,您都会将其计数为零,而应将其设置为"一"。
此代码适用于您。
statement = "The Game of Throne Rocks!"
result = {}
statement.each_char do |char|
if char == ' '
next
elsif result.include?(char)
result[char] += 1
else
result[char] = 1
end
end
result => {"T"=>2, "h"=>2, "e"=>3, "G"=>1, "a"=>1, "m"=>1, "o"=>3, "f"=>1, "r"=>1, "n"=>1, "R"=>1, "c"=>1, "k"=>1, "s"=>1, "!"=>1}
▶ statement = "The Game of Throne Rocks!"
#⇒ "The Game of Throne Rocks!"
▶ statement.downcase.delete(' ').split('').group_by(&:itself).map do |k, v|
▷ [k, v.size]
▷ end.to_h
#⇒ {"t"=>2, "h"=>2, "e"=>3, "g"=>1, "a"=>1, "m"=>1, "o"=>3,
# "f"=>1, "r"=>2, "n"=>1, "c"=>1, "k"=>1, "s"=>1, "!"=>1}
一个很好的例子,展示了如何使用不同的解决方案解决相同的问题。
您的解决方案存在缺陷,因为即使字符出现过一次,您也会将计数器初始化为
0
。如果修复此问题,那么它将按预期工作:
statement.each_char do |char|
if char == ' '
next
elsif result.include?(char)
result[char] += 1
else
result[char] = 1
end
end
您可以使用inject
或each-with_objcet
来改进代码。像这样,你不需要在循环之前初始化哈希。我更喜欢each_with_object
,因为您不需要像处理inject
那样从块中返回累积对象。
count = statement.each_char.inject({}) do |hash, char|
hash[char] = (hash[char] || 0) + 1 if char != ' '
hash
end
count = statement.each_char.each_with_object({}) do |char, hash|
hash[char] = (hash[char] || 0) + 1 if char != ' '
end
在这里,我们使用链接 http://ruby-doc.org/core-2.3.0/Enumerable.html 方法的可能性,因为它们在没有给出块时返回 en Enumerator
。
(hash[char] || 0) + 1
部分初始化计数器以在第一次出现时1
,并防止nil + 1
情况。你可以像这样写两行:
hash[char] = 0 if hash[char].nil?
hash[char] += 1
您可以通过使用初始化为0
找不到的键的哈希来"简化"该部分。
count = statement.each_char.each_with_object(Hash.new(0)) do |char, hash|
hash[char] += 1 if char != ' '
end
你也可以使用mudasobwa的解决方案,通过使用itself
非常聪明。我只会将其更改为使用 each_char
而不是
split('')
:
statement.downcase.delete(' ').each_char.group_by(&:itself).map do |k, v|
[k, v.size]
end.to_h