2014-05-03 179 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 

該字符串的其餘部分被處理相同的方式。