#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