Поскольку Ник ответил на ваш вопрос, я просто предлагаю другой способ, которым это можно сделать. Поскольку «высокий счет» является неопределенным, я предлагаю вам вернуть хэш с сокращенными словами и их соответствующими подсчетами. Начиная с Ruby 1.9, хэши сохраняют порядок ввода пар ключ-значение, поэтому мы можем захотеть воспользоваться этим и вернуть хэш с парами ключ-значение, упорядоченными в порядке убывания значений.
код
def words_by_count(str)
str.gsub(/./) do |c|
case c
when /\w/ then c.downcase
when /\s/ then c
else ''
end
end.split
.group_by {|w| w}
.map {|k,v| [k,v.size]}
.sort_by(&:last)
.reverse
.to_h
end
words_by_count('Words in a short, short words, lists of words!')
Метод Array#h был введен в Ruby, 2.1. Для более ранних версий Ruby, но необходимо использовать:
Hash[str.gsub(/./)... .reverse]
Пример
words_by_count('a short list of words with some words')
#=> {"words"=>2, "of"=>1, "some"=>1, "with"=>1,
# "list"=>1, "short"=>1, "a"=>1}
words_by_count('Words in a short, short words, lists of words!')
#=> {"words"=>3, "short"=>2, "lists"=>1, "a"=>1, "in"=>1, "of"=>1}
words_by_count('a short list of words with some short words in it')
#=> {"words"=>2, "short"=>2, "it"=>1, "with"=>1,
# "some"=>1, "of"=>1, "list"=>1, "in"=>1, "a"=>1}
Объяснение
Вот что происходит во втором примере, где:
str = 'Words in a short, short words, lists of words!'
str.gsub(/./) do |c|...
соответствует каждому символу в строке и отправляет его в блок, чтобы решить, что с ним делать.Как видите, словальные символы опущены, пробелы оставлены в покое, а все остальное преобразуется в пустое пространство.
s = str.gsub(/./) do |c|
case c
when /\w/ then c.downcase
when /\s/ then c
else ''
end
end
#=> "words in a short short words lists of words"
Это сопровождается
a = s.split
#=> ["words", "in", "a", "short", "short", "words", "lists", "of", "words"]
h = a.group_by {|w| w}
#=> {"words"=>["words", "words", "words"], "in"=>["in"], "a"=>["a"],
# "short"=>["short", "short"], "lists"=>["lists"], "of"=>["of"]}
b = h.map {|k,v| [k,v.size]}
#=> [["words", 3], ["in", 1], ["a", 1], ["short", 2], ["lists", 1], ["of", 1]]
c = b.sort_by(&:last)
#=> [["of", 1], ["in", 1], ["a", 1], ["lists", 1], ["short", 2], ["words", 3]]
d = c.reverse
#=> [["words", 3], ["short", 2], ["lists", 1], ["a", 1], ["in", 1], ["of", 1]]
d.to_h # or Hash[d]
#=> {"words"=>3, "short"=>2, "lists"=>1, "a"=>1, "in"=>1, "of"=>1}
c = b.sort_by(&:last)
Обратите внимание, что, d = c.reverse
можно заменить:
d = b.sort_by { |_,k| -k }
#=> [["words", 3], ["short", 2], ["a", 1], ["in", 1], ["lists", 1], ["of", 1]]
но sort
следуют reverse
, как правило, быстрее.
Связанные вопрос: http://stackoverflow.com/q/10695392/1301972 –
Спасибо за помощь Everone. Я обнаружил при ближайшем рассмотрении, что в словах. Я смотрел на «нитку» без сглаживания, что, казалось, решало обе мои проблемы. – ACIDSTEALTH
@ NickVeys дал хороший ответ (заработал мой +1) и является единственным, кто отвечает на ваш вопрос, поэтому понятно, что вы наградите его зеленой галочкой. Тем не менее, я бы предположил, что в будущем вы можете немного отойти (возможно, час или дольше), прежде чем выбирать ответ, поскольку относительно быстрый отбор, как правило, препятствует другим, возможно, лучшим ответам, а также упреждает читателей, которые все еще готовят ответы. –