Ruby v2.4 + (текущий)
Следующий код был невозможен в стандартном ruby, когда этот вопрос был впервые задан (февраль 2011 г.), так как он использует:
Эти современные дополнения к Ruby обеспечивают следующую реализацию:
names = ["Jason", "Jason", "Teresa", "Judah", "Michelle", "Judah", "Judah", "Allison"]
names.group_by(&:itself).transform_values(&:count)
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}
Ruby v2.2 + (устарело)
Если используется более старая версияверсия ruby, без доступа к вышеупомянутому методу Hash#transform_values
, вместо этого вы можете использовать Array#to_h
, который был добавлен в Ruby v2.1.0 (выпущен в декабре 2013 года):
names.group_by(&:itself).map { |k,v| [k, v.length] }.to_h
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}
Для даже более старых версий ruby (<= 2.1
) есть несколько способов решить эту проблему, но (на мой взгляд) не существует четкого «лучшего» способа.См. Другие ответы на этот пост.
(февраль 2019 г.) Редактировать:
Ruby v2.7 + (еще не выпущен)
Считайте этот комментарий заполнителемна будущее;Я обновлю этот пост, когда будет выпущен ruby 2.7.0
(ожидается в декабре 2019 г.), чтобы подтвердить, что метод работает на языке ядра.
В последнее время улучшено в языке .Если все пойдет по плану, мы ожидаем увидеть новый метод, Enumerable#tally
, добавленный к ruby v2.7.0.Этот метод добавляет новый синтаксис специально для этой проблемы:
names = ["Jason", "Jason", "Teresa", "Judah", "Michelle", "Judah", "Judah", "Allison"]
names.tally
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}