2010-01-21 19 views
14

Dire che ho un modello di blog con titolo e corpo. Come faccio a mostrare il numero di parole nel corpo e i personaggi nel titolo? Voglio l'uscita di essere qualcosa di simileConteggio parole in Rails?

Titolo: Lorem Corpo: Lorem Lorem Lorem

questo post conteggio delle parole di 3.

risposta

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

UPDATE: se è necessario far corrispondere rock-and-roll come una parola, si potrebbe fare come

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

Questo è esattamente quello che stavo cercando. Grazie. –

+2

Cosa ne pensi di "aggiungere un po 'di rock-n-roll"? Ci sono tre parole qui mentre la tua variante ne troverà cinque. – IDBD

+0

aggiunto anche il trattino. – YOU

16

anche:

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

Ho sperimentato che questo metodo è molto più affidabile, il/[\ w -] +/regex non sembra molto affidabile. –

+2

Mi piace molto di più. Semplice. Ho aggiunto 'squish' prima dello' split'. – duma

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

Se siete interessati in termini di prestazioni, ho scritto un rapido punto di riferimento:

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

I risultati:

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) 

In altre parole, squish è lento con il Very Large stringhe ™. Oltre a questo, split è più veloce (due volte più veloce se non si utilizza squish).

2

Le risposte qui sono un paio di questioni:

  1. Essi non tengono conto di UTF e unicode caratteri diacritici(): áâãêü ecc ...
  2. Essi non tengono conto di apostrofi e trattini . Quindi Joe's saranno considerati due parole Joe e 's che è ovviamente errato. Come sarà twenty-two, che è una singola parola composta.

Qualcosa del genere funziona meglio e conto di questi problemi:

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

Si potrebbe desiderare di guardare il mio Words Counted gioiello. Permette di contare le parole, le loro occorrenze, lunghezze e un paio di altre cose. È anche molto ben documentato.

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 

Ma, come si può vedere, la frase ha solo 3 parole. Il problema è correlato con i caratteri accentati, perché il regex \ w non li considera come un carattere di parola [A-Za-z0-9_].

Una migliore soluzione sarebbe

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