2010-01-21 16 views
14

Supongamos que tengo un modelo de blog con título y cuerpo. ¿Cómo muestro el número de palabras en el cuerpo y los personajes en el título? Quiero que la salida sea algo como estoRecuento de palabras en Rails?

Título: Lorem cuerpo: Lorem Lorem Lorem

Esta entrada no tiene cuenta de la palabra de 3.

Respuesta

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

ACTUALIZACIÓN: si usted necesita para que coincida rock and roll como una sola palabra, que podrían hacer como

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

eso es exactamente lo que estaba buscando. Gracias. –

+2

¿Qué tal "agregar algo de rock-n-roll"? Aquí hay tres palabras, mientras que su variante encontrará cinco. – IDBD

+0

añadido guión también. – YOU

16

también:

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

que he experimentado este método a ser mucho más fiable, el/[\ w -] +/expresiones regulares no parece muy fiable. –

+2

me gusta esto mucho más. Sencillo. Añadí '' squish' antes de la split'. – duma

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

Si usted está interesado en el rendimiento, escribí un punto de referencia rápida:

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 } } 

Los resultados:

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) 

En otras palabras, squish es lento con el Very Large Strings ™. Aparte de eso, split es más rápido (el doble de rápido si no está usando squish).

2

Las respuestas aquí tienen un par de cuestiones:

  1. Ellos no tienen en cuenta y Unicode UTF caracteres (diacríticos): áâãêü etc ...
  2. Ellos no dan cuenta de apóstrofes y guiones . Por lo tanto, Joe's se considerarán dos palabras Joe y 's que obviamente son incorrectas. Como será twenty-two, que es una sola palabra compuesta.

Algo como esto funciona mejor y dar cuenta de estas cuestiones:

foo.scan(/[\p{Alpha}\-']+/) 

Es posible que desee mirar a mi joya Words Counted. Permite contar palabras, sus ocurrencias, longitudes y un par de otras cosas. También está muy bien documentado.

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 

Pero como podemos ver, la frase tiene sólo 3 palabras. El problema está relacionado con los caracteres acentuados, porque el regex \ w no los considera como un carácter de palabra [A-Za-z0-9_].

Una solución mejorada sería

I18n.transliterate("caçapão adipisicing elit").scan(/[\w-]+/).size 
=> 3 
Cuestiones relacionadas