Ruby самое длинное слово в массиве

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

он возвращает либо самое длинное слово в массиве, либо массив равных длинных слов.

class Array
  def longest_word
    # Convert array elements to strings in the event that they're not.
    test_array = self.collect { |e| e.to_s }
    test_array.inject() do |word, comparison|
      if word.kind_of?(Array) then
        if word[0].length == comparison.length then
          word << comparison
        else
          word[0].length > comparison.length ? word : comparison
        end
      else
        # If words are equal, they are pushed into an array
        if word.length == comparison.length then
          the_words = Array.new
          the_words << word
          the_words << comparison
        else
          word.length > comparison.length ? word : comparison
        end
      end
    end
  end
end

6 ответов


Я бы сделал

class Array
  def longest_word
    group_by(&:size).max.last
  end
end

Ruby имеет стандартный метод для возврата элемента в списке с максимальным значением.

anArray.max{|a, b| a.length <=> b.length}

или вы можете использовать метод max_by

anArray.max_by(&:length)

чтобы получить все элементы с максимальной длиной

max_length = anArray.max_by(&:length).length
all_with_max_length = anArray.find_all{|x| x.length = max_length}

здесь один, используя inject (не работает для пустого массива):

words.inject(['']){|a,w|
  case w.length <=> a.last.length
  when -1
    a
  when 0
    a << w
  when 1
    [w]
  end
}

который можно сократить до

words.inject(['']){|a,w|
  [a + [w], [w], a][w.length <=> a.last.length]
}

для тех, кто любит гольф.


два вкладыша:

vc = ['asd','s','1234','1235'].sort{|a,b| b.size <=> a.size}
vc.delete_if{|a| a.size < vc.first.size} 


#Output
["1235", "1234"]

или если вы хотите использовать inject, это использует вашу идею, но более короткую.

test_array.inject{ |ret,word|
   ret = [ret] unless ret.kind_of?(Array)

   ret << word  if word.size == ret.first.size
   ret = [word] if word.size > ret.first.size
   ret
}

module Enumerable
  def longest_word
    (strings = map(&:to_s)).
      zip(strings.map(&:length)).
      inject([[''],0]) {|(wws, ll), (w, l)|
        case  l <=> ll
        when -1 then [wws, ll] 
        when  1 then [[w], l]
        else         [wws + [w], ll]
        end
      }.first
  end
end

этот метод зависит только от generic Enumerable методы, нет ничего Array специфическое об этом, поэтому мы можем вытащить его в Enumerable модуль, где он будет доступен для Setили Enumerators, а не просто Arrays.


Это решение использует метод inject для накопления самых длинных строк в массиве, а затем выбирает строки с наибольшей длиной.

animals = ["мышь", "кошка", "птица", "медведь", "лось"]

животные.inject(хэш.новый {/h, k / h[k] = []}) {/acc, e / acc[e.size]

Это возвращает: ["мышь", "мышь"]