Ответ 1
"Lorem Lorem Lorem".scan(/\w+/).size
=> 3
UPDATE: если вам нужно совместить рок-н-ролл как одно слово, вы можете сделать как
"Lorem Lorem Lorem rock-and-roll".scan(/[\w-]+/).size
=> 4
Скажем, у меня есть модель блога с названием и телом. Как я показываю количество слов в теле и персонажах в заголовке? Я хочу, чтобы результат был чем-то вроде этого
Название: Lorem Тело: Lorem Lorem Lorem
У этого сообщения есть число слов 3.
"Lorem Lorem Lorem".scan(/\w+/).size
=> 3
UPDATE: если вам нужно совместить рок-н-ролл как одно слово, вы можете сделать как
"Lorem Lorem Lorem rock-and-roll".scan(/[\w-]+/).size
=> 4
также:
"Lorem Lorem Lorem".split.size
=> 3
Если вы заинтересованы в производительности, я написал быстрый тест:
require 'benchmark'
require 'bigdecimal/math'
require 'active_support/core_ext/string/filters'
# Where "shakespeare" is the full text of The Complete Works of William Shakespeare...
puts 'Benchmarking shakespeare.scan(/\w+/).size x50'
puts Benchmark.measure { 50.times { shakespeare.scan(/\w+/).size } }
puts 'Benchmarking shakespeare.squish.scan(/\w+/).size x50'
puts Benchmark.measure { 50.times { shakespeare.squish.scan(/\w+/).size } }
puts 'Benchmarking shakespeare.split.size x50'
puts Benchmark.measure { 50.times { shakespeare.split.size } }
puts 'Benchmarking shakespeare.squish.split.size x50'
puts Benchmark.measure { 50.times { shakespeare.squish.split.size } }
Результаты:
Benchmarking shakespeare.scan(/\w+/).size x50
13.980000 0.240000 14.220000 ( 14.234612)
Benchmarking shakespeare.squish.scan(/\w+/).size x50
40.850000 0.270000 41.120000 ( 41.109643)
Benchmarking shakespeare.split.size x50
5.820000 0.210000 6.030000 ( 6.028998)
Benchmarking shakespeare.squish.split.size x50
31.000000 0.260000 31.260000 ( 31.268706)
Другими словами, squish
медленнее с Very Large Strings ™. Кроме того, split
работает быстрее (в два раза быстрее, если вы не используете squish
).
В ответах есть несколько проблем:
Joe's
будет считаться двумя словами Joe
и 's
, что, очевидно, неверно. Как и twenty-two
, которое представляет собой одно составное слово.Что-то вроде этого работает лучше и учитывает эти проблемы:
foo.scan(/[\p{Alpha}\-']+/)
Возможно, вы захотите посмотреть на мой Words Counted. Это позволяет подсчитывать слова, их появление, длину и пару других вещей. Он также очень хорошо документирован.
counter = WordsCounted::Counter.new(post.body)
counter.word_count #=> 3
counter.most_occuring_words #=> [["lorem", 3]]
# This also takes into capitalisation into account.
# So `Hello` and `hello` are counted as the same word.
"Lorem Lorem Lorem".scan(/\S+/).size
=> 3
"caçapão adipisicing elit".scan(/[\w-]+/).size
=> 5
Но, как мы видим, в предложении всего 3 слова. Проблема связана с акцентированными символами, потому что регулярное выражение \w не рассматривает их как символ слова [A-Za-z0-9_].
Улучшенное решение будет
I18n.transliterate("caçapão adipisicing elit").scan(/[\w-]+/).size
=> 3