2009-03-04 25 views

risposta

29

Ok, appena buttato un po 'di codice per tempo il vostro metodo di contro questo:

int count = 0; 
for (int i = 0; i < s.Length; i++) 
{ 
    if (char.IsUpper(s[i])) count++; 
} 

Il risultato:

Distinti: 19737 zecche

Mine: 118 zecche

bella differenza! A volte il modo più diretto è il più efficiente.

Modifica

solo per interesse, questo:

int count = s.Count(c => char.IsUpper(c)); 

entra a a circa 2500 zecche. Quindi per una linea "Linqy" è piuttosto veloce.

+1

+1 bella soluzione vecchia scuola :) –

+0

D'oh! Pipped at the post, quasi esattamente la stessa soluzione. Ben fatto, Matt, dannatamente stupide dita lente. . . –

+0

A proposito, +1 compagno, l'hai guadagnato :) –

3

Stai contando solo standard ASCII e non Ade ecc

Come su

CommentText.ToCharArray().Where(c => Char.IsUpper(c)).Count() 
+0

grazie per questo - Stavo cercando c.Upper in intellisense - non pensavo all'altro. – peterorum

+0

Non dimenticare: conta il numero di lettere maiuscole indipendentemente dal numero di parole. – PeterCo

3

Senza nemmeno test direi

int count = 0; 
foreach (char c in commentText) 
{ 
    if (Char.IsUpper(c)) 
     count++; 
} 

è più veloce, fuori ora per testarlo.

+0

Sì che è alla pari (o forse anche qualche tick più veloce) rispetto al mio ciclo "for". –

+0

Non mi preoccupo di provarlo, visto che Matt Hamilton è stato abbastanza premuroso da fare questo per me :) –

6

Innanzitutto non è necessario chiamare il numero ToCharArray() poiché, supponendo che CommentText sia una stringa, è già un IEnumerable<char>. In secondo luogo, dovresti probabilmente chiamare char.IsUpper invece di assumere che stai trattando solo con valori ASCII. Il codice in realtà dovrebbe assomigliare,

CommentText.Count(char.IsUpper) 

terzo luogo, se siete preoccupati per la velocità non c'è molto che può battere il vecchio ciclo for,

int count = 0; 
for (int i = 0; i < CommentText.Length; i++) 
    if (char.IsUpper(CommentText[i]) count++; 

In generale, si chiama qualsiasi metodo sta andando per essere più lento di inserire il codice, ma questo tipo di ottimizzazione dovrebbe essere fatto solo se sei assolutamente sicuro che questo è il collo del tuo codice.

+0

Amico, dovrebbe "c'è molto" essere "non c'è molto"? –

+0

Doh, si. Fisso. – chuckj

+0

Grazie per la risposta. Codice linq molto succinto. – peterorum

2

Quello che stai facendo con quel codice è creare una collezione con i personaggi, quindi creare una nuova collezione contenente solo i caratteri maiuscoli, quindi scorrere attraverso quella raccolta solo per scoprire quanti ce ne sono.

Questo si esibirà meglio (ma ancora non abbastanza buono come un ciclo semplice), in quanto non crea le collezioni intermedi:

CommentText.Count(c => Char.IsUpper(c)) 

Edit: Rimosso la chiamata ToCharArray anche, come suggerito Matt.

+0

+1 per spostare il predicato nel conteggio. Portare via il ToCharArray e accelera notevolmente. –

+0

Buon punto. Ho fatto qualcosa di simile prima e poi era necessario il ToCharArray, ma non in questo caso. :) – Guffa

2

Ho questo

Regex x = new Regex("[A-Z]{1}", 
    RegexOptions.Compiled | RegexOptions.CultureInvariant); 
int c = x.Matches(s).Count; 

ma non so se particolarmente veloce. Essa non sarà possibile ottenere i caratteri speciali o, Suppongo

EDIT:

Confronto veloce di risposta di questa domanda. Debug in vshost, 10'000 iterazioni con la stringa:
aBcDeFGHi1287jKK6437628asghwHllmTbynerA

  • La risposta: 20-30 ms
  • La soluzione regex: 140-170 ms
+0

Grazie per il confronto - mi sono chiesto come si sarebbe impilato un regex. – peterorum

+0

È possibile schiacciare questo in una riga: 'Regex.Matches (s," [A-Z] {1} ", RegexOptions.Compiled | RegexOptions.CultureInvariant) .Count;' –

Problemi correlati