2010-01-21 5 views
14

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

Название: Lorem тела: Lorem Lorem Lorem

Это сообщение имеет количество слов 3.

ответ

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

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

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

Это именно то, что я искал. Благодарю. –

+2

Как насчет «добавить рок-н-ролл»? Здесь есть три слова, в то время как ваш вариант найдет пять. – IDBD

+0

добавлен дефис. – YOU

16

также:

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

Я испытал этот метод, чтобы быть намного более надежным,/[\ w -] +/regex не кажется очень надежным. –

+2

Мне это больше нравится. Просто. Я добавил «squish» перед «split». – duma

4

Если вы заинтересованы в работе, я написал быстрый тест:

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 является медленным с очень большой Струны ™. Кроме того, split быстрее (в два раза быстрее, если вы не используете squish).

2

Ответы здесь есть несколько вопросов:

  1. Они не учитывают и UTF юникод символов (диакритические): áâãêü и т.д ...
  2. Они не учитывают апострофов и дефисов , Таким образом, 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. 
1
"caçapão adipisicing elit".scan(/[\w-]+/).size 
=> 5 

Но, как мы видим, предложение имеет только три слова. Проблема связана с акцентированными символами, потому что регулярное выражение \ w не рассматривает их как символ слова [A-Za-z0-9_].

улучшенное решением будет

I18n.transliterate("caçapão adipisicing elit").scan(/[\w-]+/).size 
=> 3 
Смежные вопросы