Как мне упростить решение этой рубиновой проблемы, которая требует удвоения каждой согласной в заданной строке?

Таким образом, вопрос требует, чтобы я «Написал метод, который принимает строку и возвращает новую строку, в которой каждый согласный символ удваивается. Гласные (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!" но я ищу более краткое решение. Я пробовал [a-z^aeiou]/i и подобные комбинации, но они также удваивали гласные. Так что, если кто-то может проинструктировать меня, как правильно объединить два выражения, а также объяснить мне, почему моя элементарная попытка была ошибочной, я был бы чрезвычайно признателен. Кроме того, любые предложения или исправления в остальной части моего кода также приветствуются.

Ваш ответ работает. double_consonants('abcdefg') #=> "abbccddeffgg".

Sagar Pandya 07.04.2019 04:38

Попробуйте: if char =~ /[bcdfghjklmnpqrstvwxyz]/i

Matt.G 07.04.2019 04:41

Да, я знаю, что мой ответ работает, но я искал более простое решение, которое сочетает в себе два моих условия, если это возможно. @SagarPandya

Purge Ibaka 07.04.2019 04:46

Спасибо @Matt.G, это сработало, но, честно говоря, я искал рабочую версию [a-z^aeiou]/i, чтобы лучше понять механизм регулярных выражений.

Purge Ibaka 07.04.2019 04:51

Это /[a-z&&[^aeiou]]/ от здесь. Тогда другим способом использования gsub будет str.gsub(/([a-z&&[^aeiou]])/i,'\1\1')

Sagar Pandya 07.04.2019 05:09

Несколько очень мелких моментов. 1) Начиная с Ruby v2.4 вы можете писать char.match?(/[a-z]/i) вместо char =~ /[a-z]/i. Первый, возможно, читается лучше и возвращает логическое значение, а не строковый индекс (вы бы его не использовали) или nil. 2. Вы можете написать char !~ /aeiou/i вместо char =~ /[^aeiou]/i. (продолжение...)

Cary Swoveland 07.04.2019 06:20

...3. string.chars возвращает временный массив. Поскольку map является методом Enumerable, для него требуется получатель, который является перечислителем, вместо этого вы можете написать string.each_char.map, поскольку each_char возвращает перечислитель, а не временный массив, экономя память. Используйте each_char, за исключением случаев, когда используется цепочка с методом Array, и в этом случае вы должны использовать chars (например, string.chars.product(...)).

Cary Swoveland 07.04.2019 06:21

Обратите внимание, что вам не нужна переменная array. Удалите array = и array.join и замените end, который заканчивает блок map, на end.join. Напомним, что каждый блок возвращает значение. Вот вариант, который позволяет избежать преобразования в массив и последующего join, а также включает предложение @Sagar: "Cats!".each_char.with_object('') { |c,s| s << (c.match?(/[a-z&&[^aeiou]]/i) ? c*2 : c) } # #=> "CCattss!". Кстати, поскольку ваш код работает, ваш вопрос действительно больше подходит для дочернего сайта SO на Stack Exchange, Обзор кода. Посмотри!

Cary Swoveland 07.04.2019 06:52

Спасибо, @SagarPanya, ваше решение ближе всего к тому решению, которое я себе представлял.

Purge Ibaka 08.04.2019 03:53

@CarySwoveland, ты рок-звезда. Ваше более крупное решение было очень тщательным, и ваше предложение использовать матч? вместо метода регулярного выражения =~ имеет смысл и с ним легче работать. Кстати, я буквально завел профиль прямо перед тем, как запостить эту проблему и был в шоке от скорости ответов. Я хочу поблагодарить вас и всех, кто нашел время, чтобы помочь мне.

Purge Ibaka 08.04.2019 04:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
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."

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

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

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

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

и заменить на \1\1

Демо

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

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