Количество слов в Rails?

Скажем, у меня есть модель блога с названием и телом. Как я показываю количество слов в теле и персонажах в заголовке? Я хочу, чтобы результат был чем-то вроде этого

Название: Lorem Тело: Lorem Lorem Lorem

У этого сообщения есть число слов 3.

Ответы

Ответ 1

"Lorem Lorem Lorem".scan(/\w+/).size
=> 3

UPDATE: если вам нужно совместить рок-н-ролл как одно слово, вы можете сделать как

"Lorem Lorem Lorem rock-and-roll".scan(/[\w-]+/).size
=> 4

Ответ 2

также:

"Lorem Lorem Lorem".split.size
=> 3

Ответ 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).

Ответ 4

В ответах есть несколько проблем:

  • Они не учитывают символы utf и unicode (диакритики): áâãêü и т.д.
  • Они не учитывают апострофы и дефисы. Таким образом, 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.

Ответ 5

"Lorem Lorem Lorem".scan(/\S+/).size
=> 3

Ответ 6

"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