Использовать выражение регулярных выражений в карте замен gsub?

Я пытаюсь заставить это работать:

def self.simultaneos_gsub(arguments)
  map_of_regex = Hash[arguments]
  re = Regexp.union(map_of_regex.keys)
  s = self.gsub(re, map_of_regex)
end

Аргументы будут примерно такими:

[[/[0-9]/i, '-'], [/@/, 'T']]

Так "019@hey" должен вернуться "---They",

Лучший пример того, что я хочу, это:

arguments = [[/[a-z]/i, '@'], [/@/, '-']]

Input: 'This is just a @234' should return => '@@@ @@ @@@@ @ -234'

gsub находит правильные символы, но заменяет их пустыми.

Есть идеи?

4 ответа

[18] pry(main)> s = "019@hey"
=> "019@hey"
[19] pry(main)> [[/[0-9]/i, '-'], [/@/, 'T']].each { |k,v| s.gsub!(k, v) }
=> [[/[0-9]/i, "-"], [/@/, "T"]]
[20] pry(main)> s
=> "---They"

переписанный метод, поэтому args может быть хешем, например { /[0-9]/i => '-', /@/ => 'T' } или массив, содержащий массивы, каждый из которых имеет 2 элемента, например [[/[0-9]/i, '-'], [/@/, 'T']]

def simultaneous_gsub(string, args)
   st = string.dup
   args.each { |k,v| st = st.gsub(k, v) }
   st
end

Пример использования:

string = "019@hey"
simultaneous_gsub(string, { /[0-9]/i => '-', /@/ => 'T' })
#=> "---They"
or
string = "019@hey"
simultaneous_gsub(string, [[/[0-9]/i, '-'], [/@/, 'T']])
#=> "---They"

Может быть, это поможет разложить вещи:

class String
  def simultaneos_gsub(arguments)
    map_of_regex = Hash[arguments]
    re = Regexp.union(map_of_regex.keys)  # => /0|1|2|3|4|5|6|7|8|9|@/, /a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|@|T/
    self.gsub(re, map_of_regex)           # => "---They", "@@@@ @@ @@@@ @ -234"
  end
end

arguments = Hash[('0'..'9').zip(['-'] * 10)]
arguments['@'] = 'T'
arguments # => {"0"=>"-", "1"=>"-", "2"=>"-", "3"=>"-", "4"=>"-", "5"=>"-", "6"=>"-", "7"=>"-", "8"=>"-", "9"=>"-", "@"=>"T"}
"019@hey".simultaneos_gsub(arguments) # => "---They"

arguments = Hash[('a' .. 'z').zip(['@'] * 26)]
arguments.merge!({'@' => '-', 'T' => '@'})
# should return => '@@@ @@ @@@@ @ -234'
'This is just a @234'.simultaneos_gsub(arguments) # => "@@@@ @@ @@@@ @ -234"

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

Если вам действительно нужно, чтобы gsub выполнялся в одной строке, вы можете создать хеш, представляющий все возможные символы соответствия, сопоставленные с их символом замены. Документация относительно предоставления хеша в качестве аргумента gsub можно найти здесь

Вот код, который может это сделать. Это не красиво, но кажется, что вы довольно gsub вызывается только один раз.

Вот что я бы сделал:

# Create a hash that looks like this...
# replacement_hash = { 
#   'a' => '@',
#   'b' => '@',
#   ...
#   'Z' => '@',
#   '@' => '-' }

replacement_hash = {}
(('a'..'z').to_a + ('A'..'Z').to_a).each { |char| replacement_hash[char] = '@' }
replacement_hash['@'] = '-'

'This is just a @234'.gsub(/[a-zA-Z\@]/, replacement_hash)  # => "@@@@ @@ @@@@ @ -234"

Предостережения

Чтобы получить эту работу в рамках вашей функции, вам необходимо предоставить карту сопоставленных строк с их соответствующими заменами. Тогда ваше регулярное выражение должно быть чередованием (|) между всеми этими возможными поисковыми строками. Это немного легче осуществить, как указано выше, когда это просто один символ, замененный другим символом / символом /.

Если вы не женаты на gsubВы можете сделать это с помощью рекурсии, split, а также join:

class String
  def simultaneos_gsub(arguments)
    if arguments.empty?
      self
    else
      argument = arguments.pop
      parts = split(argument.first)
      parts.collect! {|part| part.simultaneos_gsub(arguments) }
      parts.join(argument.last)
    end
  end
end

arguments = [[/[a-z]/i, "@"], [/@/, "-"]]
string = "This is just a @234"

string.simultaneos_gsub(arguments)
#=> "@@@@ @@ @@@@ @ -234"

Это позволяет избежать проблемы, которую, я полагаю, вы пытаетесь решить gsubЧасть строки, которую вы уже заменили несколько раз, удаляет части строки, которую вы заменяете, а затем добавляете их обратно в качестве значения замены.

Другие вопросы по тегам