Императивный подход, который вы использовали, является, вероятно, самой быстрой реализацией в Ruby.Немного реорганизовав, вы можете написать однострочник:
wf = Hash.new(0).tap { |h| words.each { |word| h[word] += 1 } }
Другой императивный подход с использованием Enumerable#each_with_object
:
wf = words.each_with_object(Hash.new(0)) { |word, acc| acc[word] += 1 }
Функциональный / неизменный подход с использованием существующих абстракций:
wf = words.group_by(&:itself).map { |w, ws| [w, ws.length] }.to_h
Обратите внимание, что это все еще O (n) во времени, но оно проходит через коллекцию три раза и создает два промежуточных объекта на этом пути.
Наконец: частотомер / гистограмма - это общая абстракция, которую вы найдете в некоторых библиотеках, таких как Facets: Enumerable # частоты .
require 'facets'
wf = words.frequency