2014-05-03 100 views
0

当试图找到在“梦幻般的”我无法理解给定的解决方案字母频率:频率在字符串中的字母

def letter_count(str) 
    counts = {} 

    str.each_char do |char| 
    next if char == " " 
    counts[char] = 0 unless counts.include?(char) 
    counts[char] += 1 
    end 

    counts 
end 

我试图解构它,当我创建了下面的一段代码我希望它做同样的事情。但它给了我不同的结果。

blah = {} 
x = 'fantastic' 
    x.each_char do |char| 
     next if char == " " 
     blah[char] = 0 
      unless 
      blah.include?(char) 
      blah[char] += 1 
    end 
blah 
end 

的第一段代码给我下面的

puts letter_count('fantastic') 
> 
{"f"=>1, "a"=>2, "n"=>1, "t"=>2, "s"=>1, "i"=>1, "c"=>1} 

为什么代码的第二件让我

puts blah 
> 
{"f"=>0, "a"=>0, "n"=>0, "t"=>0, "s"=>0, "i"=>0, "c"=>0} 

有人能打破的代码片段,并告诉我根本的区别是什么。我想,一旦我明白了这一点,我就能够真正理解第一段代码。另外如果你想解释一下关于帮助我的第一段代码,那也会很棒。

回答

2

您不能分割这条线......

counts[char] = 0 unless counts.include?(char) 

...在多个行,你所采取的方式。尾随条件仅适用于一行。

如果您想要将其拆分为多行,您必须将其转换为传统的if/end(在这种情况下除非/ end)格式。

unless counts.include?(char) 
    counts[char] = 0 
end 

下面的代码的解释...

# we define a method letter_count that accepts one argument str 
def letter_count(str) 

    # we create an empty hash 
    counts = {} 

    # we loop through all the characters in the string... we will refer to each character as char 
    str.each_char do |char| 

    # we skip blank characters (we go and process the next character) 
    next if char == " " 

    # if there is no hash entry for the current character we initialis the 
    # count for that character to zero 
    counts[char] = 0 unless counts.include?(char) 

    # we increase the count for the current character by 1 
    counts[char] += 1 

    # we end the each_char loop 
    end 

    # we make sure the hash of counts is returned at the end of this method 
    counts 

# end of the method 
end 
2

现在@Steve已经回答了你的问题,你接受了他的答案,或许我可以建议另一种方式来计算的字母。这只是可以采取的许多方法之一。

代码

def letter_count(str) 
    str.downcase.each_char.with_object({}) { |c,h| 
    (h[c] = h.fetch(c,0) + 1) if c =~ /[a-z]/ } 
end 

letter_count('Fantastic') 
    #=> {"f"=>1, "a"=>2, "n"=>1, "t"=>2, "s"=>1, "i"=>1, "c"=>1} 

说明

这里是发生了什么。

str = 'Fantastic' 

我们使用String#downcase,这样,例如,'f''F'被视为计数的目的,相同的字符。 (如果你不希望出现这种情况,只需删除.downcase)让

s = str.downcase #=> "fantastic" 

s.each_char.with_object({}) { |c,h| (h[c] = h.fetch(c,0) + 1) c =~ /[a-z]/ } 

枚举String#each_char被链接到Enumerator#with_index。这就产生了一个化合物枚举:

enum = s.each_char.with_object({}) 
    #=> #<Enumerator: #<Enumerator: "fantastic":each_char>:with_object({})> 

我们可以查看什么枚举将传递到块中,通过将其转换为一个数组:

enum.to_a 
    #=> [["f", {}], ["a", {}], ["n", {}], ["t", {}], ["a", {}], 
    # ["s", {}], ["t", {}], ["i", {}], ["c", {}]] 

(实际上,它仅通过与'f'一个空散列;之后它传递散列的更新值。)枚举器with_object创建由块变量h表示的空散列。

传递给块的第一个元素enum是字符串'f'。块变量c被分配该值,因此,在该块中的表达:

(h[c] = h.fetch(c,0) + 1) if c =~ /[a-z]/ 

的计算结果为:

(h['f'] = h.fetch('f',0) + 1) if 'f' =~ /[a-z]/ 

现在

c =~ /[a-z]/ 

true当且仅当c是一个小写字母。这里

'f' =~ /[a-z]/ #=> true 

,所以我们计算表达式

h[c] = h.fetch(c,0) + 1 

h.fetch(c,0)回报h[c]如果h有一个关键c;否则它返回值Hash#fetch的第二个参数,这里是零。 (fetch也可以采取一个块。)

由于h现在是空的,就变成

h['f'] = 0 + 1 #=> 1 

枚举each_char然后转到'a''n''t'到块,产生散列成为

h = {'f'=>1, 'a'=>1, 'n'=>1, 't'=>1 } 

传入的下一个字符是第二个'a'。作为h已经有一个关键'a'

h[c] = h.fetch(c,0) + 1 

评估为

h['a'] = h['a'] + 1 #=> 1 + 1 => 2 

该字符串的其余部分被处理相同的方式。