Власне, функція повинна повертати рядок, у якому кожне входження будь-якого рядків із перелічених у from, замінюється на відповідний рядок з to. Функція приймає один аргумент, який повинен бути масивом, індекси якого трактуються як рядки пошуку, а відповідні значення - як рядки заміни. В першу чергу замінює більш довші підрядки.
class String
def strtr(tr)
sorted_tr = tr.sort{|a, b| b[0] <=> a[0]}
keys = sorted_tr.map{|k, v| k}
values = sorted_tr.map{|k, v| v}
r = /(#{keys.map{|i| Regexp.escape(i)}.join( ')|(' )})/
self.gsub(r){|match| values[keys.index(match)]}
end
end
Приклад роботи:
tr1 = {'A' => '1', 'AA' => '2', 'AAA' => '3'}
tr2 = [['A', '1'],['AA', '2'],['AAA', '3']]
s = 'ABAACAAADAAAA'
puts s.strtr(tr1)
puts s.strtr(tr2)
1B2C3D31
1B2C3D31
UPD
Ще один варіант цієї функції. Коротший і зрозуміліший:
class String
def strtr(tr)
tr.sort{|a, b| b[0] <=> a[0]}.map.inject(self){|str, pair| str.gsub(pair[0], pair[1])}
end
end
Але він не відповідає умові, що один і той же рядок пошуку використовується тільки один раз.
При вхідних даних:
s = "ABAACAAADAAAA"
tr = {"A"=>"AA", "AA"=>"AAAA", "AAA"=>"AAAAAA"}
s.strtr(tr)
Для першого варіанту отримаємо:
=> "AABAAAACAAAAAADAAAAAAAA"
а для другого:=> "AABAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAA"
3 коментарі:
str.tr(from, to)
http://ruby-doc.org/core/classes/String.html#M000830
вже ж є таке
...хоча ні, тут приклад з парами key-value
String#tr зовсім не те, що мені було потрібне. І взагалі ця функція працює незрозумілим чином:
"A1AA2AAA3".tr('AAA', '3') => "313323333"
Тут бульше підійде String#gsub:
"A1AA2AAA3".gsub('AAA', '3') => "A1AA233"
Дописати коментар