Superiore o inferiore

Quando si effettuano confronti senza distinzione tra maiuscole e minuscole, è più efficiente convertire la stringa in maiuscolo o minuscolo? Ha importanza?

In questo post SO viene suggerito che C # è più efficiente con ToUpper perché “Microsoft l’ha ottimizzata in questo modo”. Ma ho anche letto questo argomento che la conversione da ToLower a ToUpper dipende da ciò che le stringhe contengono di più, e che in genere le stringhe contengono caratteri minuscoli che rendono ToLower più efficiente.

In particolare, vorrei sapere:

  • C’è un modo per ottimizzare ToUpper o ToLower in modo tale che uno sia più veloce dell’altro?
  • È più veloce fare un confronto insensibile alle maiuscole / minuscole tra stringhe maiuscole o minuscole e perché?
  • Esistono ambienti di programmazione (ad esempio C, C #, Python, qualunque) in cui un caso è chiaramente migliore dell’altro e perché?

    La conversione in lettere maiuscole o minuscole per fare confronti tra maiuscole e minuscole non è corretta a causa delle caratteristiche “interessanti” di alcune culture, in particolare la Turchia. Invece, usa un StringComparer con le opzioni appropriate.

    MSDN ha alcune ottime linee guida sulla gestione delle stringhe. Potresti anche voler controllare che il tuo codice superi il test di Turchia .

    EDIT: Nota il commento di Neil sui confronti ordinali insensibili alle maiuscole. Questo intero regno è piuttosto oscuro 🙁

    Da Microsoft su MSDN:

    Best practice per l’utilizzo di stringhe in .NET Framework

    Consigli per l’utilizzo delle stringhe

    • Utilizzare il metodo String.ToUpperInvariant invece del metodo String.ToLowerInvariant quando si normalizzano le stringhe per il confronto.

    Perché? Da Microsoft :

    Normalizza le stringhe in maiuscolo

    C’è un piccolo gruppo di caratteri che quando convertiti in lettere minuscole non possono effettuare un round trip.

    Qual è l’esempio di un personaggio del genere che non può fare un viaggio di andata e ritorno?

    • Inizio : simbolo greco Rho (U + 03f1) ρ
    • Maiuscolo: capitale greca Rho (U + 03a1) Ρ
    • Minuscolo: piccolo greco Rho (U + 03c1) ρ

    ρ, Ρ , ρ

    Ecco perché, se vuoi fare confronti tra maiuscole e minuscole, converti le stringhe in maiuscolo e non in minuscolo.

    Secondo MSDN è più efficiente passare le stringhe e dire al confronto di ignorare il caso:

    String.Compare (strA, strB, StringComparison.OrdinalIgnoreCase) equivale a ( ma più veloce di ) chiamare

    String.Compare (ToUpperInvariant (strA), ToUpperInvariant (strB), StringComparison.Ordinal).

    Questi confronti sono ancora molto veloci.

    Naturalmente, se si confronta una stringa più e più volte, questo potrebbe non essere valido.

    Sulla base di stringhe tendenti ad avere più voci minuscole, ToLower dovrebbe teoricamente essere più veloce (molti paragoni, ma pochi compiti).

    In C, o quando si usano elementi individualmente accessibili di ogni stringa (come le stringhe C o il tipo di stringa STL in C ++), si tratta in realtà di un confronto di byte – quindi confrontare UPPER non è diverso da quello lower .

    Se fossi subdolo e avessi caricato le tue stringhe in array long , avresti ottenuto un confronto molto veloce sull’intera stringa perché poteva confrontare 4 byte alla volta. Tuttavia, il tempo di caricamento potrebbe renderlo inutile.

    Perché hai bisogno di sapere quale è più veloce? A meno che tu non stia facendo un buttload metrico di confronti, uno eseguendo un paio di cicli più veloce è irrilevante rispetto alla velocità di esecuzione complessiva e suona come l’ottimizzazione prematura 🙂

    Microsoft ha ottimizzato ToUpperInvariant() , non ToUpper() . La differenza è che l’invariante è più favorevole alla cultura. Se hai bisogno di fare confronti senza distinzione tra maiuscole e minuscole su stringhe che possono variare in cultura, usa Invariant, altrimenti l’esecuzione della conversione invariabile non dovrebbe avere importanza.

    Non posso dire se ToUpper () o ToLower () sia più veloce. Non l’ho mai provato dal momento che non ho mai avuto una situazione in cui le prestazioni fossero così importanti.

    Se si sta eseguendo il confronto delle stringhe in C # è molto più veloce usare .Equals () invece di convertire entrambe le stringhe in maiuscolo o minuscolo. Un altro grande vantaggio per l’utilizzo di .Equals () è che non viene allocata più memoria per le 2 nuove stringhe maiuscole / minuscole.

    Davvero non dovrebbe mai importare. Con i caratteri ASCII, non ha assolutamente importanza – sono solo pochi confronti e un po ‘di capovolgimento per entrambe le direzioni. Unicode potrebbe essere un po ‘più complicato, dal momento che ci sono alcuni personaggi che cambiano caso in modi strani, ma non ci dovrebbero essere differenze se il tuo testo non è pieno di quei caratteri speciali.

    Facendolo nel modo giusto, dovrebbe esserci un piccolo, insignificante vantaggio di velocità se si converte in minuscolo, ma questo è, come molti hanno suggerito, dipendente dalla cultura e non è ereditato dalla funzione ma nelle stringhe che si convertono (molte lettere minuscole significa pochi compiti in memoria) – la conversione in maiuscolo è più veloce se si dispone di una stringa con molte lettere maiuscole.

    Dipende. Come detto sopra, solo ASCII, è identico. In .NET, leggere e utilizzare String.Compare è corretto per la roba i18n (lingue culture e unicode). Se sai qualcosa sulla probabilità dell’input, usa il caso più comune.

    Ricorda, se stai eseguendo più stringhe, la lunghezza comparativa è un eccellente discriminatore.

    Se hai a che fare con ASCII puro, non importa. È solo un OR x, 32 contro un AND x, 224. Unicode, non ne ho idea …