Руби самое длинное слово в массиве - PullRequest
8 голосов
/ 06 марта 2011

Я создал этот метод, чтобы найти самое длинное слово в массиве, но мне интересно, есть ли лучший способ сделать это.Я довольно новичок в 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 ]

27 голосов
/ 06 марта 2011

Я бы сделал

class Array
  def longest_word
    group_by(&:size).max.last
  end
end
6 голосов
/ 06 марта 2011

В 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}
4 голосов
/ 06 марта 2011

Вот один из них, использующий 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]
}

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

2 голосов
/ 06 марта 2011

Два лайнера:

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


#Output
["1235", "1234"]

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

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
}
1 голос
/ 06 марта 2011
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

Этот метод зависит только от общих Enumerable методов, в нем нет ничего конкретного Array, поэтому мы можем перенести его в модуль Enumerable, где он также будет доступен для Set sили Enumerator с, а не просто Array с.

0 голосов
/ 18 сентября 2016

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

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

animals.inject (Hash.new {| h, k | h [k] = []}) {| acc, e | acc [e.size] << e; acc} .sort.last [1] </p>

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

...