Come eseguire il confronto di stringhe senza distinzione tra maiuscole e minuscole?


1056

Come eseguire il confronto di stringhe maiuscole e minuscole in JavaScript?


25
vedere il .localeCompare()metodo javascript appena aggiunto . Supportato solo dai browser moderni al momento della scrittura (IE11 +). vedi developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Adrien,


5
@AdrienBe "A".localeCompare( "a" );ritorna 1nella console Chrome 48.
Manuell,

3
@manuell che significa che "a"viene prima "A"quando ordinato. Come "a"viene prima "b". Se questo comportamento non è desiderato, si potrebbe desiderare .toLowerCase()ogni lettera / stringa. vale a dire. "A".toLowerCase().localeCompare( "a".toLowerCase() )vedi developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
Adrien Be

2
Perché il confronto è spesso un termine usato per ordinare / ordinare le stringhe, suppongo. Ho commentato qui molto tempo fa ora. ===verificherà l'uguaglianza ma non sarà abbastanza buono per l'ordinamento / ordinamento delle stringhe (vedi la domanda a cui originariamente ho collegato).
Adrien, il

Risposte:


1163

Il modo più semplice per farlo (se non sei preoccupato per i caratteri Unicode speciali) è chiamare toUpperCase:

var areEqual = string1.toUpperCase() === string2.toUpperCase();

44
La conversione in maiuscolo o minuscolo fornisce confronti non sensibili al maiuscolo / minuscolo corretti in tutte le lingue. i18nguy.com/unicode/turkish-i18n.html
Samuel Neff,

57
@sam: lo so. Ecco perché ho scritto if you're not worried about special Unicode characters.
SLaks, il

141
C'è un motivo per preferire toUpperCasesopra toLowerCase?
jpmc26,


19
È davvero il migliore che JS ha da offrire?
Kugel,

210

EDIT : questa risposta è stata originariamente aggiunta 9 anni fa. Oggi dovresti usare localeComparecon l' sensitivity: 'accent'opzione:

function ciEquals(a, b) {
    return typeof a === 'string' && typeof b === 'string'
        ? a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0
        : a === b;
}

console.log("'a' = 'a'?", ciEquals('a', 'a'));
console.log("'AaA' = 'aAa'?", ciEquals('AaA', 'aAa'));
console.log("'a' = 'á'?", ciEquals('a', 'á'));
console.log("'a' = 'b'?", ciEquals('a', 'b'));

La { sensitivity: 'accent' }dice localeCompare()per trattare due varianti della stessa lettera di base come lo stesso meno hanno accenti diversi (come nel terzo esempio) di cui sopra.

In alternativa, puoi usare { sensitivity: 'base' }, che tratta due personaggi equivalenti purché il loro personaggio base sia lo stesso (quindi Averrebbe trattato come equivalente a á).

Si noti che il terzo parametro di localeComparenon è supportato in IE10 o browser browser inferiori o determinati (vedere la tabella di compatibilità nella pagina collegata sopra), quindi se è necessario supportare tali browser, è necessario un tipo di fallback:

function ciEqualsInner(a, b) {
    return a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0;
}

function ciEquals(a, b) {
    if (typeof a !== 'string' || typeof b !== 'string') {
        return a === b;
    }

    //      v--- feature detection
    return ciEqualsInner('A', 'a')
        ? ciEqualsInner(a, b)
        : /*  fallback approach here  */;
}

Risposta originale

Il modo migliore per eseguire un confronto senza distinzione tra maiuscole e minuscole in JavaScript è utilizzare il match()metodo RegExp con il iflag.

Ricerca senza distinzione tra maiuscole e minuscole

Quando entrambe le stringhe confrontate sono variabili (non costanti), è un po 'più complicato perché è necessario generare un RegExp dalla stringa ma passare la stringa al costruttore RegExp può provocare corrispondenze errate o corrispondenze non riuscite se la stringa ha regex speciale personaggi in esso.

Se ti interessa l'internazionalizzazione non utilizzare toLowerCase()o toUpperCase()in quanto non fornisce confronti accurati senza distinzione tra maiuscole e minuscole in tutte le lingue.

http://www.i18nguy.com/unicode/turkish-i18n.html


5
@Quandary, sì, è quello che ho detto che doveva essere gestito - "è necessario generare un RegExp dalla stringa ma passare la stringa al costruttore RegExp può provocare corrispondenze errate o corrispondenze non riuscite se la stringa contiene caratteri regex speciali"
Samuel Neff,

21
L'utilizzo di questa è la soluzione più costosa per il confronto di stringhe senza distinzione tra maiuscole e minuscole. Un RegExp è pensato per la corrispondenza di schemi complicati, come tale, deve costruire un albero decisionale per ogni modello, quindi lo esegue contro stringhe di input. Mentre funzionerebbe, è paragonabile a prendere un aereo a reazione per fare shopping al blocco successivo. tl; dr: per favore non farlo.
Agoston Horvath,

2
potrei usare localeCompare (), ma il suo ritorno -1 per 'a'.localeCompare('A')e come l'op sto cercando il confronto di stringhe senza distinzione tra maiuscole e minuscole.
StingyJack

3
@StingyJack per fare un confronto senza distinzione tra maiuscole e minuscole usando localeCompare, dovresti fare 'a'.localeCompare (' A ', indefinito, {sensibilità:' base '})
Judah Gabriel Himango

1
Nota: La localeCompareversione richiede che il motore JavaScript supporta l'API ECMAScript® Internazionalizzazione , quale è , non tenuto a fare. Quindi, prima di fare affidamento su di esso, potresti voler verificare che funzioni nell'ambiente che stai utilizzando. Ad esempio: const compareInsensitive = "x".localeCompare("X", undefined, {sensitivity: "base"}) === 0 ? (a, b) => a.localeCompare(b, undefined, {sensitivity: "base"}) : (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());o alcuni di questi.
TJ Crowder,

47

Come detto in commenti recenti, string::localeComparesupporta confronti senza distinzione tra maiuscole e minuscole (tra le altre cose potenti).

Ecco un semplice esempio

'xyz'.localeCompare('XyZ', undefined, { sensitivity: 'base' }); // returns 0

E una funzione generica che potresti usare

function equalsIgnoringCase(text, other) {
    return text.localeCompare(other, undefined, { sensitivity: 'base' }) === 0;
}

Nota che invece di undefinedte probabilmente dovresti inserire la locale specifica con cui stai lavorando. Questo è importante come indicato nei documenti MDN

in svedese, ä e a sono lettere di base separate

Opzioni di sensibilità

Opzioni di sensibilità tabulate da MDN

Supporto per il browser

Al momento della pubblicazione, UC Browser per Android e Opera Mini non supporta i parametri locali e delle opzioni . Controlla https://caniuse.com/#search=localeConfronta per informazioni aggiornate.


35

Con l'aiuto dell'espressione regolare possiamo anche raggiungere.

(/keyword/i).test(source)

/iè per ignorare il caso. Se non necessario, possiamo ignorare e verificare la corrispondenza tra maiuscole e minuscole come

(/keyword/).test(source)

17
L'uso di una regex come questa corrisponderà alle sottostringhe! Nel tuo esempio, la stringa keyWORDinduce in una corrispondenza positiva. Ma la stringa this is a keyword yoo keywordssi tradurrà anche in una corrispondenza positiva. Attenzione :-)
Elmer,

6
Questo non risponde al controllo di uguaglianza (senza distinzione tra maiuscole e minuscole) come richiesto nella domanda! Ma questo è un controllo Contains ! Non usarlo
S.Serpooshan

4
Naturalmente, per abbinare l'intera stringa, è possibile modificare regexp /^keyword$/.test(source), ma 1) se keywordnon è una costante, è necessario fare new RegExp('^' + x + '$').test(source)e 2) ricorrere a una regexp per testare qualcosa di semplice come l'uguaglianza di stringa insensibile al maiuscolo / minuscolo è per niente molto efficiente.
JHH,

28

Ricorda che l'involucro è un'operazione specifica della locale. A seconda dello scenario, ti consigliamo di tenerne conto. Ad esempio, se si stanno confrontando nomi di due persone, è possibile prendere in considerazione le impostazioni locali, ma se si stanno confrontando valori generati dalla macchina come UUID, è possibile che non si desideri. Questo è il motivo per cui utilizzo la seguente funzione nella mia libreria utils (nota che il controllo del tipo non è incluso per motivi di prestazioni).

function compareStrings (string1, string2, ignoreCase, useLocale) {
    if (ignoreCase) {
        if (useLocale) {
            string1 = string1.toLocaleLowerCase();
            string2 = string2.toLocaleLowerCase();
        }
        else {
            string1 = string1.toLowerCase();
            string2 = string2.toLowerCase();
        }
    }

    return string1 === string2;
}

C'è un motivo per cui usi "!!" eseguire una conversione booleana esplicita, invece di consentire alla clausola if di valutare la veridicità dei valori?
Celos,

Non è richiesto Immagino di averlo ottenuto dall'altra mia versione di codice più complicato. Ho aggiornato la risposta.
Shital Shah,

@thekodester la tua funzione ha un bug. Ciò compareStrings("", "")darà falsenonostante il fatto che le stringhe sono uguali.
Sergey,

@Sergey Fare questo ritorna trueper me. Forse è un bug con il tuo browser?
Jenna Sloan,

14

Di recente ho creato una micro libreria che fornisce helper di stringhe senza distinzione tra maiuscole e minuscole: https://github.com/nickuraltsev/ignore-case . (Utilizza toUpperCaseinternamente.)

var ignoreCase = require('ignore-case');

ignoreCase.equals('FOO', 'Foo'); // => true
ignoreCase.startsWith('foobar', 'FOO'); // => true
ignoreCase.endsWith('foobar', 'BaR'); // => true
ignoreCase.includes('AbCd', 'c'); // => true
ignoreCase.indexOf('AbCd', 'c'); // => 2

12

se sei preoccupato per la direzione della disuguaglianza (forse vuoi ordinare un elenco) devi praticamente fare la conversione di maiuscole e minuscole, dato che ci sono più caratteri minuscoli in Unicode che mai in MaiuscoleCase è probabilmente la migliore conversione da usare.

function my_strcasecmp( a, b ) 
{
    if((a+'').toLowerCase() > (b+'').toLowerCase()) return 1  
    if((a+'').toLowerCase() < (b+'').toLowerCase()) return -1
    return 0
}

Javascript sembra utilizzare la locale "C" per i confronti delle stringhe, quindi l'ordine risultante sarà brutto se le stringhe contengono lettere diverse da quelle ASCII. non c'è molto che si possa fare al riguardo senza fare un'ispezione molto più dettagliata delle stringhe.


7

Supponiamo di voler trovare la variabile stringa needlenella variabile stringa haystack. Ci sono tre gotcha:

  1. Le applicazioni internazionalizzate dovrebbero evitare string.toUpperCasee string.toLowerCase. Utilizzare un'espressione regolare che ignora invece il caso. Ad esempio, var needleRegExp = new RegExp(needle, "i");seguito da needleRegExp.test(haystack).
  2. In generale, potresti non conoscere il valore di needle. Fare attenzione che needlenon contenga caratteri speciali di espressioni regolari . Fuggi da questi usando needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");.
  3. In altri casi, se vuoi abbinare con precisione needlee haystack, semplicemente ignorando il caso, assicurati di aggiungere "^"all'inizio e "$"alla fine del tuo costruttore di espressioni regolari.

Prendendo in considerazione i punti (1) e (2), un esempio potrebbe essere:

var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i");
var result = needleRegExp.test(haystack);
if (result) {
    // Your code here
}

Scommetti! Tutto quello che dovete fare è sostituire la new RegExp(...)parte in linea 3 con il seguente: new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");. Questo si assicura che non ci siano altri caratteri prima o dopo la stringa di ricerca needle.
Chris Chute,

4

Esistono due modi per il confronto senza distinzione tra maiuscole e minuscole:

  1. Converti le stringhe in maiuscolo e poi confrontale usando l'operatore rigoroso ( ===). In che modo gli operatori rigorosi trattano gli operandi leggendo le informazioni su: http://www.thesstech.com/javascript/relational-logical-operators
  2. Corrispondenza del modello mediante metodi stringa:

Utilizzare il metodo di stringa "cerca" per la ricerca senza distinzione tra maiuscole e minuscole. Leggi la ricerca e altri metodi di stringa su: http://www.thesstech.com/pattern-matching-using-string-methods

<!doctype html>
  <html>
    <head>
      <script>

        // 1st way

        var a = "apple";
        var b = "APPLE";  
        if (a.toUpperCase() === b.toUpperCase()) {
          alert("equal");
        }

        //2nd way

        var a = " Null and void";
        document.write(a.search(/null/i)); 

      </script>
    </head>
</html>

4

Molte risposte qui, ma mi piace aggiungere un sollution basato sull'estensione della lib String:

String.prototype.equalIgnoreCase = function(str)
{
    return (str != null 
            && typeof str === 'string'
            && this.toUpperCase() === str.toUpperCase());
}

In questo modo puoi semplicemente usarlo come fai in Java!

Esempio:

var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
    document.write("a == b");
}
if (a.equalIgnoreCase(c)) {
    document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
    document.write("b != c");
}

L'output sarà:

"a == b"
"b != c"

String.prototype.equalIgnoreCase = function(str) {
  return (str != null &&
    typeof str === 'string' &&
    this.toUpperCase() === str.toUpperCase());
}


var a = "hello";
var b = "HeLLo";
var c = "world";

if (a.equalIgnoreCase(b)) {
  document.write("a == b");
  document.write("<br>");
}
if (a.equalIgnoreCase(c)) {
  document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
  document.write("b != c");
}


4

Utilizzare RegEx per la corrispondenza o il confronto delle stringhe.

In JavaScript, puoi utilizzare match()per il confronto delle stringhe, non dimenticare di inserire iRegEx.

Esempio:

var matchString = "Test";
if (matchString.match(/test/i)) {
  alert('String matched');
}
else {
 alert('String not matched');
}

1
Assicurati di stare bene con le partite parziali, altrimenti matchString.match(/^test$/i).
hackel

Che cosa invece di "test" minuscolo hai var x = 'test', matchString.match(/x/i)funzionerebbe? In caso contrario, cosa funzionerebbe?
Razvan Zamfir,

3
str = 'Lol', str2 = 'lOl', regex = new RegExp('^' + str + '$', 'i');
if (regex.test(str)) {
    console.log("true");
}

3

Se entrambe le stringhe hanno le stesse impostazioni locali note, potresti voler usare un Intl.Collatoroggetto come questo:

function equalIgnoreCase(s1: string, s2: string) {
    return new Intl.Collator("en-US", { sensitivity: "base" }).compare(s1, s2) === 0;
}

Ovviamente, potresti voler memorizzare nella cache Collatorper una migliore efficienza.

Il vantaggio di questo approccio è che dovrebbe essere molto più veloce rispetto all'utilizzo di RegExps e si basa su un set estremamente personalizzabile (vedi descrizione localese optionsparametri del costruttore nell'articolo sopra) di collator pronti all'uso.


Un'altra opzione per la sensibilità è accent, che la rende insensibile al maiuscolo / minuscolo, ma tratta ae ácome personaggi separati. Quindi baseo accentpotrebbe essere appropriato a seconda delle esigenze esatte.
Matthew Crumley,

2

Ho scritto un'estensione. molto banale

if (typeof String.prototype.isEqual!= 'function') {
    String.prototype.isEqual = function (str){
        return this.toUpperCase()==str.toUpperCase();
     };
}

1
Cosa succede due basi di codice con idee diverse su come String # isEqual dovrebbe funzionare cercando di esistere contemporaneamente?
Ryan Cavanaugh,

3
@KhanSharp Molte persone considerano un anti-schema per modificare il prototipo di tipi incorporati. Ecco perché le persone potrebbero non votare la tua risposta.
jt000,

1
Non è sconsiderato preferire definizioni di metodi sconosciute? Ad esempio, non appena alcuni browser decidono di implementare String#isEqualo Object#isEqualnativamente tutte le tue pagine si comportano diversamente e potrebbero fare cose strane se le specifiche non corrispondono esattamente alle tue.
Robert,

2

Anche questa domanda ha già risposto. Ho un approccio diverso per usare RegExp e abbinare per ignorare la distinzione tra maiuscole e minuscole. Si prega di consultare il mio link https://jsfiddle.net/marchdave/7v8bd7dq/27/

$("#btnGuess").click(guessWord);

  function guessWord() {

   var letter = $("#guessLetter").val();
   var word = 'ABC';
   var pattern = RegExp(letter, 'gi'); // pattern: /a/gi

   var result = word.match(pattern);
   alert('Ignore case sensitive:' + result);

  }

1

Che ne dici di NON lanciare eccezioni e di NON usare la regex lenta?

return str1 != null && str2 != null 
    && typeof str1 === 'string' && typeof str2 === 'string'
    && str1.toUpperCase() === str2.toUpperCase();

Lo snippet sopra riportato presuppone che non si desideri trovare una corrispondenza se una stringa è nulla o non definita.

Se si desidera abbinare null / undefined, quindi:

return (str1 == null && str2 == null)
    || (str1 != null && str2 != null 
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase());

Se per qualche motivo ti interessa undefined vs null:

return (str1 === undefined && str2 === undefined)
    || (str1 === null && str2 === null)
    || (str1 != null && str2 != null 
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase());

O semplicementestr1 == str2 || ...
SLaks,

1

Poiché nessuna risposta ha chiaramente fornito un semplice frammento di codice da utilizzare RegExp, ecco il mio tentativo:

function compareInsensitive(str1, str2){ 
  return typeof str1 === 'string' && 
    typeof str2 === 'string' && 
    new RegExp("^" + str1.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + "$", "i").test(str2);
}

Ha diversi vantaggi:

  1. Verifica il tipo di parametro (qualsiasi parametro non stringa, come undefined ad esempio, causerebbe il crash di un'espressione simile str1.toUpperCase()).
  2. Non soffre di possibili problemi di internazionalizzazione.
  3. Esce dalla RegExpstringa.

Ma soffre della mancanza di regexp in fuga.
Qwertiy,

@Qwertiy fair point, aggiunta escape per stackoverflow.com/a/3561711/67824 .
Ohad Schneider,

0

Questa è una versione migliorata di questa risposta .

String.equal = function (s1, s2, ignoreCase, useLocale) {
    if (s1 == null || s2 == null)
        return false;

    if (!ignoreCase) {
        if (s1.length !== s2.length)
            return false;

        return s1 === s2;
    }

    if (useLocale) {
        if (useLocale.length)
            return s1.toLocaleLowerCase(useLocale) === s2.toLocaleLowerCase(useLocale)
        else
            return s1.toLocaleLowerCase() === s2.toLocaleLowerCase()
    }
    else {
        if (s1.length !== s2.length)
            return false;

        return s1.toLowerCase() === s2.toLowerCase();
    }
}



Usi e test:


0

Converti entrambi in basso (solo una volta per motivi di prestazioni) e confrontali con l'operatore ternario in un'unica riga:

function strcasecmp(s1,s2){
    s1=(s1+'').toLowerCase();
    s2=(s2+'').toLowerCase();
    return s1>s2?1:(s1<s2?-1:0);
}

Chi dice che C è morto? : D
Seth,

0

Se sai che hai a che fare con il asciitesto, puoi semplicemente usare un confronto tra caratteri maiuscoli / minuscoli.

Assicurati solo che la stringa con la quale la stringa "perfetta" (quella a cui vuoi abbinare) sia minuscola:

const CHARS_IN_BETWEEN = 32;
const LAST_UPPERCASE_CHAR = 90; // Z
function strMatchesIgnoreCase(lowercaseMatch, value) {
    let i = 0, matches = lowercaseMatch.length === value.length;
    while (matches && i < lowercaseMatch.length) {
        const a = lowercaseMatch.charCodeAt(i);
        const A = a - CHARS_IN_BETWEEN;
        const b = value.charCodeAt(i);
        const B = b + ((b > LAST_UPPERCASE_CHAR) ? -CHARS_IN_BETWEEN : CHARS_IN_BETWEEN);
        matches = a === b // lowerA === b
            || A === b // upperA == b
            || a === B // lowerA == ~b
            || A === B; // upperA == ~b
        i++;
    }
    return matches;
}

0

Mi piace questa rapida variazione abbreviata -

export const equalsIgnoreCase = (str1, str2) => {
    return (!str1 && !str2) || (str1 && str2 && str1.toUpperCase() == str2.toUpperCase())
}

Elaborazione rapida e fa quello che è previsto.


0

Questa javascript libreria sembra fornire molte operazioni sulle stringhe. È molto comodo da usare

Come installare

npm install --save string

Importare

var S = require('string');

Ignorecase Compare String

var isEqual = S('ignoreCase').equalsIgnoreCase('IGNORECASE')
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.