str = "Hello☺ World☹"
Очікуваний результат:
"Hello:) World:("
Я можу зробити це: str.gsub("☺", ":)").gsub("☹", ":(")
Чи є інший спосіб, щоб я міг зробити це за один виклик функції ?. Щось на зразок:
str.gsub(['s1', 's2'], ['r1', 'r2'])
str = "Hello☺ World☹"
Очікуваний результат:
"Hello:) World:("
Я можу зробити це: str.gsub("☺", ":)").gsub("☹", ":(")
Чи є інший спосіб, щоб я міг зробити це за один виклик функції ?. Щось на зразок:
str.gsub(['s1', 's2'], ['r1', 'r2'])
String#tr
зробити трюк, але заміни, які є кількома символами, означають, що я не можу цим користуватися.
Відповіді:
Оскільки Ruby 1.9.2, String#gsub
приймає хеш як другий параметр для заміни відповідними ключами. Ви можете використовувати регулярний вираз, щоб відповідати підрядку, який потрібно замінити, і передати хеш для значень, які потрібно замінити.
Подобається це:
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') #=> "h3ll*"
'(0) 123-123.123'.gsub(/[()-,. ]/, '') #=> "0123123123"
У Ruby 1.8.7 ви б досягли того ж за допомогою блоку:
dict = { 'e' => 3, 'o' => '*' }
'hello'.gsub /[eo]/ do |match|
dict[match.to_s]
end #=> "h3ll*"
tr
.
Створіть таблицю відображення:
map = {'☺' => ':)', '☹' => ':(' }
Потім побудуйте регулярний вираз:
re = Regexp.new(map.keys.map { |x| Regexp.escape(x) }.join('|'))
І нарешті gsub
:
s = str.gsub(re, map)
Якщо ви застрягли в 1,8 землі, то:
s = str.gsub(re) { |m| map[m] }
Вам потрібно Regexp.escape
там, якщо щось, що ви хочете замінити, має особливе значення в регулярному виразі. Або, завдяки steenslag, ви можете використовувати:
re = Regexp.union(map.keys)
і цитування подбає про вас.
map.each { |re, v| ... }
Ви можете зробити щось подібне:
replacements = [ ["☺", ":)"], ["☹", ":("] ]
replacements.each {|replacement| str.gsub!(replacement[0], replacement[1])}
Може бути більш ефективне рішення, але це, принаймні, робить код трохи чистішим
replacements.each
?
each
- це колекція, до якої було викликано. stackoverflow.com/questions/11596879/…
replacements.reduce(str){|str,replacement| str.gsub(replacement[0],replacement[1])}
replacements.inject(str) { |str, (k,v)| str.gsub(k,v) }
і уникати необхідності робити [0]
і [1]
.
Пізно на вечірку, але якщо ви хочете замінити певні символи на один, ви можете використовувати регулярний вираз
string_to_replace.gsub(/_|,| /, '-')
У цьому прикладі gsub замінює підкреслення (_), коми (,) або () тире (-)
string_to_replace.gsub(/[_- ]/, '-')
Ще один простий спосіб, і все ж легкий для читання, полягає в наступному:
str = '12 ene 2013'
map = {'ene' => 'jan', 'abr'=>'apr', 'dic'=>'dec'}
map.each {|k,v| str.sub!(k,v)}
puts str # '12 jan 2013'
Ви також можете використовувати tr для заміни кількох символів у рядку одночасно,
Наприклад, замініть "h" на "m" і "l" на "t"
"hello".tr("hl", "mt")
=> "metto"
виглядає просто, акуратно і швидше (хоч і не така різниця), ніж gsub
puts Benchmark.measure {"hello".tr("hl", "mt") }
0.000000 0.000000 0.000000 ( 0.000007)
puts Benchmark.measure{"hello".gsub(/[hl]/, 'h' => 'm', 'l' => 't') }
0.000000 0.000000 0.000000 ( 0.000021)