2014-11-16 2 views
0

Я немного смущенно поведением downcase в этом случае, если я изменить мой код из этогоhas_key в сочетании с .downcase не работает должным образом

module FunWithStrings 
def count_words 
    hash = Hash.new 
    self.split(" ").each do |i| 
     i.downcase! 
     if !hash.has_key?(i) 
     hash[i] = 1 
     else 
     hash[i] += 1 
     end 
    end 
    hash 
    end 
end 

class String 
    include FunWithStrings 
end 


p "test hello test Test wow".count_words 

выхода будет собственно с правильным колом { "теста "=> 3," hello "=> 1," wow "=> 1} Если я попытаюсь свести к минимуму код и переключить его на i.downcase! в функции функции has_key он выводит неверные значения. Не знаю, почему.

module FunWithStrings 

    def count_words 
    hash = Hash.new 
    self.split(" ").each do |i| 
     if !hash.has_key?(i.downcase!) 
     hash[i] = 1 
     else 
     hash[i] += 1 
     end 
    end 
    hash 
    end 
end 

class String 
    include FunWithStrings 
end 


p "test hello test Test wow".count_words 

{ "Тест" => 2, "привет" => 1, "вау" => 1}

ответ

4

Что вы испытываете, потому что вы звонишь String#downcase! и не String#downcase. Если запустить IRB и проверить это вы увидите:

> "TeSt".downcase! 
=> "test" 
> "test".downcase! 
=> nil 
> "TeSt".downcase 
=> "test" 
> "test".downcase 
=> "test" 

Что здесь происходит, что если строка уже в нижнем регистре, то String#downcase! вернется nil; однако альтернатива String#downcase всегда будет возвращать действительную строчную строку, даже если начальная строка уже имеет строчные буквы. Также важно отметить, что String#downcase! изменяет строковый объект, на который ссылается переменная, которая может быть или не быть желаемым результатом.

> s = "TeSt" 
=> "TeSt" 
> s.downcase! 
=> "test" 
> s 
=> "test" 

Это, как правило, не то, что вы хотели бы сделать, вместо этого вы хотите, чтобы вызвать немаркированные downcase, который возвращает новый объект String, который представляет строчную версию строки.

Смежные вопросы