Используйте Reduce, чтобы изменить некоторые слова в строке в ruby - PullRequest
0 голосов
/ 20 февраля 2019
keywords = ["fish", "blue"]
phrase = 'one fish two fish red fish blue fish'
actual = ???

assert_equal 'one FISH two FISH red FISH BLUE FISH', actual

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

В длинных есть способ использовать, чтобы уменьшить, чтобы изменить каждое слово в строке, для которой выполняется условие.В этом случае я хочу upcase каждый word в phrase, который включен в keywords.Я мог бы представить, что мог бы использовать этот метод с некоторыми изменениями, чтобы удалить каждый экземпляр слова или заменить его.Я знаю о sub и gsub, но я делаю набор задач, который наводит меня на мысль, что это возможно с помощью Reduce.Я был в документах безрезультатно.

Меня интересуют только решения, использующие уменьшение, или объяснение, почему в этом случае сокращение не работает.

Я заставил его работать, используя,

actual = keywords.reduce('one fish two fish red fish blue fish'){|memo,word| memo.gsub(word,word.upcase) }

Комментарий Гаррета направил меня в правильном направлении.Возможно, я был неясен, изначально я просто не хотел решения gsub за пределами reduce.Спасибо за помощь!

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

tl; dr

f1 = def upcase_fish(str); str.gsub('fish', 'FISH'); end
f2 = def upcase_blue(str); str.gsub('blue', 'BLUE'); end
[f1, f2].reduce(phrase){ |str, f| Method.send f, str }

Объяснение

Вызов нескольких функций, например, вывод одной функции является вводом следующей функции, является распространенным случаем использования.Например, здесь у нас есть две функции: одна с большой буквы «рыба», а другая - «синий».Конечно, мы могли бы добавить и другие преобразования, такие как удаление конечных пробелов, использование заглавных букв и т. Д. В функциональном программировании это может быть достигнуто путем сокращения набора функций.Сначала мы инициализируем результат с исходным значением phrase, а затем применяем f1, а затем f2.Это эквивалентно: f2(f1(phrase)).

0 голосов
/ 20 февраля 2019

Вот несколько способов сделать это.Оба должны быть относительно эффективными и использовать метод String # gsub и регулярное выражение:

r = /\p{Alpha}+/

Это соответствует одной или нескольким буквам Unicode.

keywords = ["fish", "blue"]
phrase = "one fish two Fish red fisH blue fish."

Обратите внимание, что в первой заглавной букве «Рыба» я выделил букву «H» во втором «FisH» и добавил точку.

Используйте форму String#gsub, в которой используется хешдля выполнения подстановок

subs = keywords.each_with_object({}) { |word,h|
  h[word] = word.capitalize }
  #=> {"fish"=>"Fish", "blue"=>"Blue"} 
subs.default_proc = Proc.new { |_,word|
  subs.include?(word.downcase) ? word.upcase : word } 
  #=> #<Proc:0x000059dc26dd1510@(irb):95> 
phrase.gsub(r, subs)
  #=> "one Fish two FISH red FISH Blue Fish." 

Процедура по умолчанию возвращает строку, если word не является ключом subs.Если word.downcase является ключом subs, возвращается word.upcase;иначе word возвращается без изменений.См. Hash # default_proc = .

Использование набора для ускорения поиска

require 'set'

subs = keywords.to_set
  #=> #<Set: {"fish", "blue"}> 
phrase.gsub(r) { |word|
  subs.include?(word.downcase) ? word.upcase : word }
  #=> "one FISH two FISH red FISH BLUE FISH."  
0 голосов
/ 20 февраля 2019

Если вы используете Reduce, я думаю, вы можете начать с разделения строки на пробелы (если она нормализована, чтобы всегда иметь разделение на один пробел), а затем проверить, находится ли текущее слово в блоке в массиве ключевых слов, если так,вставьте его в заметку, его версию в верхнем регистре плюс пробел справа, в противном случае просто слово (плюс пробел):

new_phrase = phrase.split.reduce('') do |memo, word|
  pushed_word = if keywords.include?(word)
                  word.upcase
                else
                  word
                end
  memo << "#{pushed_word} "
end

p new_phrase
# "one FISH two FISH red FISH BLUE FISH "

Поскольку вы закончите с одним дополнительным правым пробелом, вы можете использовать rstrip чтобы избавиться от этого.

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