Метод Ruby gsub — принимает хэш?

#ruby

#ruby

Вопрос:

Предполагается, что строковый метод Ruby gsub должен принимать хэш. Как написано здесь:

http://www.ruby-doc.org/core/classes/String.html#M001185

«Если второй аргумент является хэшем, а сопоставленный текст является одним из его ключей, соответствующее значение является заменяющей строкой».

Они приводят пример:

 'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"
  

Проблема в том, что у меня это не работает (ruby 1.8.7):

 in `gsub': can't convert Hash into String (TypeError)
  

Это происходит для точно такой же строки. Почему?

Ответ №1:

Это потому, что документ, который упоминает OP, предназначен для ruby 1.9.2 . Для ruby 1.8.7 , обратитесь к http://www.ruby-doc.org/core-1.8.7/classes/String.html#M000792 ; там gsub метод не принимает хэш в качестве параметра.

ОБНОВЛЕНИЕ: Вы можете добавить эту функцию в свой код:

 class String
  def awesome_gsub(pattern, hash)
    gsub(pattern) do |m| 
      hash[m]
    end
  end
end

p 'hello'.awesome_gsub(/[eo]/, 'e' => '3', 'o' => '*') #=> "h3ll*"
  

Комментарии:

1. Извините за это. Спасибо, @sepp2k. Исправлено.

Ответ №2:

Это особенность, специфичная для Ruby 1.9.

В документации Ruby 1.8.7 об этом ничего не упоминается: http://www.ruby-doc.org/core-1.8.7/classes/String.html

Ответ №3:

 "hello".gsub( /([eo])/ ){ {'e' => 3, 'o' => '*'}[$1] }
  

Комментарии:

1. Это сложно для простого хэша операции, но просмотр блока может помочь, если у вас хэши большего размера.

Ответ №4:

Возможно, вы захотите посмотреть, будут ли обратные порты включать функциональность 1.9.2 в 1.8.7.

Ответ №5:

Добавьте это в класс хэша вашего проекта:

 # replaces recursively old_value by new_value
def gsub_hash_values(old_value, new_value)
  self.each do |k, v|
    if v.is_a?(Array)
      v.each do |vv|
        vv.gsub!(old_value, new_value)
      end
    elsif v.is_a?(Hash)
      v.gsub_hash_values(old_value, new_value)
    elsif v.respond_to?(:to_s)
     self[k] = v.to_s.gsub(old_value, new_value)
    end
  end
end