Как мне упростить мое решение этой проблемы с рубином, которая требует, чтобы каждый согласный был удвоен в данной строке? - PullRequest
0 голосов
/ 07 апреля 2019

Итак, вопрос спрашивает: «Напишите метод, который принимает строку и возвращает новую строку, в которой каждый согласный символ удваивается. Гласные (a, e, i, o, u), цифры, пунктуация и пробелне должно быть удвоено ".Ну, я быстро понял, что регулярное выражение должно сработать, но я довольно новичок в таких выражениях и поэтому должен был использовать оператор &&, чтобы заставить мое решение работать.Теперь я уверен, что это легко исправить, но я не смог его создать, поэтому вот мое решение проблемы:

def double_consonants(string)
  array = string.chars.map do |char| 
    if char =~ /[a-z]/i && char =~ /[^aeiou]/i
      char * 2
    else 
      char 
    end 
  end 
  array.join 
end 

Так что double_consonants ("Hello World!") Правильно выводит "HHellllo WWorrlldd!"но я ищу более сжатое решение.Я пробовал [az ^ aeiou] / i и подобные комбинации, но они также удваивали гласные.Так что, если кто-то может научить меня, как правильно комбинировать два выражения, а также объяснить мне, почему моя рудиментарная попытка была неправильной, я был бы чрезвычайно благодарен.Кроме того, любые предложения или исправления к остальной части моего кода также приветствуются.

Ответы [ 2 ]

1 голос
/ 07 апреля 2019
MAPPING =
  (('a'..'z').to_a - %w|a e i o u|).
    each_with_object({}) do |s,h|
      h[s] = s + s
      h[s.upcase] = h[s].upcase
    end.tap { |h| h.default_proc = proc { |_,c| c } } 
  #=> {"b"=>"bb", "c"=>"cc", "d"=>"dd", "f"=>"ff",..."z"=>"zz",
  #    "B"=>"BB", "C"=>"CC", "D"=>"DD", "F"=>"FF",..."Z"=>"ZZ"} 

MAPPING['c']  #=> "cc" 
MAPPING['C']  #=> "CC" 
MAPPING['a']  #=> "a" 
MAPPING['$']  #=> "$" 

"Now is the time to party, said 007.".gsub(/./, MAPPING)
  #=> "NNoww iss tthhe ttimme tto pparrttyy, ssaidd 007."

Используется форма String # gsub , которая использует хэш (MAPPING) для выполнения подстановок.Первый аргумент gsub, регулярное выражение /./ вызывает сопоставление каждого символа строки.

Чтобы это работало, MAPPING[c] (c переменная) должна возвращать cдля каждого символа c это не является согласной.Это достигается путем присоединения к хешу по умолчанию proc (proc { |_,c| c }).См. Hash # default_proc = и Kernel # tap .

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

0 голосов
/ 07 апреля 2019

, если вам нужно решение для регулярных выражений, подобное тому, которое было опубликовано в вопросе, попробуйте регулярное выражение: (?=[a-z])(?![aeiou])(.)

и замените его на \1\1

Демо

Возвращаясь к регулярному выражению, указанному в вопросе: [a-z^aeiou] соответствует одному символу в диапазоне от a (index 97) до z (index 122) или ^ или a или e или i или o или u (без учета регистра) (подробности см. в описании, приведенном в правом верхнем углу этой демонстрации )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...