Короткий и эффективный код Ruby для преобразования массива слов в перетасованную строку, разделенную запятыми, с «и» перед последним словом?

#ruby #string #interpolation #shuffle

Вопрос:

Я хотел бы преобразовать такой массив:

 ["apple","banana","pineapple","plum","pear"]
 

Для

 I like plum, pineapple, banana, pear *and* apple.
 

Мой текущий код выглядит так:

 %Q{
   I like #{%w[apple banana pineapple plum pear].shuffle.yield_self{|q| [q[0..-2].join(", "),q[-1]].join(" and ") }}
  }
 

Есть ли еще какой-нибудь подход %w[умный, чистый и эффективный рубиновый].magic ()?

Ответ №1:

Я не знаю, умнее это или чище, но поехали:

 def to_sentence(ary)
  ary = ary.dup.shuffle
  [ary.pop, ary.join(', ')].reverse.join(' and ')
end
 

Ответ №2:

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

 arr = ["apple", "banana", "pineapple", "plum", "pear"]
 

#1

  def to_sentence(arr)
  *all_but_last, last = arr.shuffle
  all_but_last.join(', ') << ' and ' << last
end
 
 to_sentence(arr)
  #=> "pear, plum, pineapple, apple and banana"
to_sentence(arr)
  #=> "banana, pear, pineapple, plum and apple"
to_sentence(arr)
  #=> "banana, plum, apple, pineapple and pear"
to_sentence(arr)
  #=> "banana, pineapple, pear, apple and plum"
 

#2

  def to_sentence(arr)
  arr.shuffle.join(', ').sub(/,(?!.*,)/, ' and')
 end
 
  to_sentence(arr)
   #=> "banana, plum, pear, apple and pineapple"
 to_sentence(arr)
   #=> "pear, plum, pineapple, banana and apple"
 to_sentence(arr)
   #=> "apple, pineapple, plum, pear and banana"
 to_sentence(arr)
   #=> "apple, plum, pear, pineapple and banana"
 

Регулярное выражение соответствует запятой, за которой в строке не следует другая запятая (то есть она соответствует последней запятой в строке). (?!.*,) это негативный взгляд.

Регулярное выражение также может быть записано

 /.*K,/
 

.* соответствует любому символу, отличному от завершителей строк, как можно большему числу (включая запятые), потому * что по умолчанию является жадным. K затем сбрасывает начало совпадения в текущее местоположение в строке (прямо перед последней запятой) и удаляет все ранее использованные символы из возвращаемого совпадения. Затем сопоставляется запятая, которая обязательно является последней запятой в строке.