Büyük / küçük harf duyarsız dize karşılaştırması nasıl yapılır?


1056

JavaScript'te büyük / küçük harfe duyarlı olmayan dize karşılaştırmasını nasıl yapabilirim?


25
yeni eklenen .localeCompare()javascript yöntemine bakın. Yazma sırasında yalnızca modern tarayıcılar tarafından desteklenir (IE11 +). bkz. developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Adrien Be


5
@AdrienBe , Chrome 48 Konsoluna "A".localeCompare( "a" );geri döner 1.
manuell

3
@manuell yani sıralandığında daha "a"önce gelir "A". Daha "a"önce olduğu gibi "b". Bu davranış istenmiyorsa, .toLowerCase()her harf / dize için isteyebilirsiniz . yani. "A".toLowerCase().localeCompare( "a".toLowerCase() )bkz. developer.mozilla.org/tr/docs/Web/JavaScript/Reference/…
Adrien Be

2
Çünkü karşılaştırma genellikle sanırım dizeleri sıralamak / sıralamak için kullanılan bir terimdir. Buraya uzun zaman önce yorum yaptım. ===eşitliği kontrol eder ancak dizeleri sıralamak / sıralamak için yeterince iyi olmaz (bkz. başlangıçta bağlandığım soru).
Adrien Be

Yanıtlar:


1162

Bunu yapmanın en basit yolu (özel Unicode karakterleri hakkında endişelenmiyorsanız) aramak toUpperCase:

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

44
Büyük veya küçük harfe dönüştürme, tüm dillerde büyük / küçük harfe duyarlı olmayan karşılaştırmalar sağlar. i18nguy.com/unicode/turkish-i18n.html
Samuel Neff

57
@sam: Biliyorum. Bu yüzden yazdım if you're not worried about special Unicode characters.
SLaks

141
Tercih için bir neden var mı toUpperCaseüzerinde toLowerCase?
jpmc26


19
Bu gerçekten JS'nin sunabileceği en iyi şey mi?
Kugel

210

EDIT : Bu cevap ilk 9 yıl önce eklendi. Bugün localeCompareşu sensitivity: 'accent'seçenekle kullanmalısınız :

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'));

Yukarıda farklı aksanlar (üçüncü örnekte olduğu gibi) olmadığı sürece aynı taban harfinin iki varyantını aynı olarak işlemeyi { sensitivity: 'accent' }söyler .localeCompare()

Alternatif { sensitivity: 'base' }olarak, taban karakterleri aynı olduğu sürece iki karaktere eşdeğer davranan (böylece Aeşdeğer kabul edilir á) kullanabilirsiniz.

Not Bunun Üçüncü parametre localeCompareIE10 desteklenen veya düşürmek veya bu tarayıcıları desteklemek gerekiyorsa, son çare çeşit gerekir böylece belirli mobil tarayıcılar, (yukarıda bağlantısı sayfadaki uyum tablosuna bakın) değildir:

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  */;
}

Orijinal cevap

JavaScript'te büyük / küçük harf duyarsız bir karşılaştırma yapmanın en iyi yolu match(), ibayrakla RegExp yöntemini kullanmaktır .

Büyük / küçük harfe duyarlı olmayan arama

Karşılaştırılan her iki dizge de değişkenler (sabitler değil) ise, biraz daha karmaşıktır, çünkü dizeden bir RegExp oluşturmanız gerekir, ancak dizeyi RegExp yapıcısına iletmek dizenin özel regex'i varsa yanlış eşleşmelere veya başarısız eşleşmelere neden olabilir içindeki karakterler.

Eğer uluslararası önem veriyorsanız kullanmayın toLowerCase()veya toUpperCase()tüm dillerdeki doğru harf duyarsız karşılaştırmalar sağlamaz olarak.

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


5
@Quandary, evet, işlenmesi gerektiğini söyledim - "dizeden bir RegExp oluşturmanız gerekiyor, ancak dizeyi RegExp yapıcısına iletmek dizede özel regex karakterleri varsa yanlış eşleşmelere veya başarısız eşleşmelere neden olabilir"
Samuel Neff

21
Bunu kullanmak, büyük / küçük harfe duyarlı olmayan dize karşılaştırması için en maliyetli çözümdür. RegExp, karmaşık kalıp eşleşmesi içindir, bu nedenle, her kalıp için bir karar ağacı oluşturması ve daha sonra bunu giriş dizelerine karşı yürütmesi gerekir. İşe yarayacak olsa da, bir sonraki blokta alışverişe gitmek için bir jet uçağı almak karşılaştırılabilir. tl; dr: lütfen bunu yapma.
Agoston Horvath

2
i localeCompare () kullanabilirsiniz, ama onun için dönen -1 'a'.localeCompare('A')ve op gibi ben durum duyarsız dize karşılaştırmak için arıyorum.
StingyJack

3
@StingyJack, localeCompare kullanarak büyük / küçük harfe duyarlı olmayan karşılaştırma yapmak için, 'a'.localeCompare (' A ', tanımsız, {duyarlılık:' base '})
yapmalısınız

1
Not:localeCompare sürüm JavaScript motoru destekleyen gerektirir ECMAScript® Uluslararasılaşma API bunun edilir değil yapmak için gerekli. Bu nedenle, ona güvenmeden önce, kullandığınız ortamda çalışıp çalışmadığını kontrol etmek isteyebilirsiniz. Örneğin: const compareInsensitive = "x".localeCompare("X", undefined, {sensitivity: "base"}) === 0 ? (a, b) => a.localeCompare(b, undefined, {sensitivity: "base"}) : (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());ya da bazıları.
TJ Crowder

46

Son yorumlarda belirtildiği gibi string::localeCompare, büyük / küçük harfe duyarlı olmayan karşılaştırmaları (diğer güçlü şeylerin yanı sıra) destekler.

İşte basit bir örnek

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

Ve kullanabileceğiniz genel bir işlev

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

Bunun yerine undefinedmuhtemelen birlikte çalıştığınız yerel ayarı girmeniz gerektiğini unutmayın . MDN belgelerinde belirtildiği gibi bu önemlidir

İsveççe, ä ve a ayrı temel harflerdir

Hassasiyet seçenekleri

MDN'den tablolanmış hassasiyet seçenekleri

Tarayıcı desteği

Nakil sırasında itibariyle Android ve Opera Mini için UC Tarayıcı yok desteklemek yerel ve seçenekleri parametrelerini. Güncel bilgiler için lütfen https://caniuse.com/#search=localeCompare adresini kontrol edin .


35

Düzenli ifade yardımıyla da başarabiliriz.

(/keyword/i).test(source)

/igörmezden gelinmesi içindir. Gerekmiyorsa, büyük / küçük harfe duyarlı olmayan eşleşmeyi yok sayabilir ve test edebiliriz

(/keyword/).test(source)

17
Bunun gibi bir normal ifade kullanmak alt dizelerle eşleşir! keyWORDÖrneğinizde , dize pozitif bir eşleşme ile sonuçlanacaktır. Ancak dize this is a keyword yoveya keywordspozitif bir eşleşme ile sonuçlanacaktır. Bunun farkında olun :-)
Elmer

6
Bu , soruda sorulduğu gibi Eşitlik kontrolüne (büyük / küçük harfe duyarsız) cevap vermez ! Ama, bu bir İçerir çek! Kullanmayın
S.Serpooshan

4
Tabii ki, tüm dizgiyi eşleştirmek için normal ifade değişebilir /^keyword$/.test(source), ancak 1) keywordsabit değilse, yapmanız gerekir new RegExp('^' + x + '$').test(source)ve 2) büyük / küçük harf duyarsız dize eşitliği kadar basit bir şeyi test etmek için normal ifadeye başvurmak hiç de çok verimli.
JHH

28

Muhafazanın bölgeye özgü bir işlem olduğunu unutmayın. Senaryoya bağlı olarak bunu hesaba katmak isteyebilirsiniz. Örneğin, iki kişinin adlarını karşılaştırıyorsanız, yerel ayarı dikkate almak isteyebilirsiniz, ancak UUID gibi makine tarafından üretilen değerleri karşılaştırıyorsanız, bunu yapamayabilirsiniz. Bu yüzden utils kütüphanemde aşağıdaki işlevi kullanıyorum (performans nedeniyle tip kontrolünün dahil olmadığını unutmayın).

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

"!!" kullanmanız için bir neden var mı? if deyiminin değerlerin doğruluğunu değerlendirmesine izin vermek yerine açık bir boolean dönüşümü gerçekleştirmek için?
Celos

Gerekli değil. Sanırım daha karmaşık kodların diğer versiyonundan aldım. Cevabı güncelledim.
Shital Shah

@thekodester işlevinizde bir hata var. Bu , dizelerin eşit olmasına rağmen compareStrings("", "")verecektir false.
Sergey

@Sergey Bunu yapmak truebenim için geri döner . Belki de tarayıcınızla ilgili bir hata mı?
Jenna Sloan

14

Son zamanlarda büyük / küçük harfe duyarlı olmayan dize yardımcıları sağlayan bir mikro kütüphane oluşturdum: https://github.com/nickuraltsev/ignore-case . ( toUpperCaseDahili olarak kullanır .)

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

eşitsizliğin yönüyle ilgili endişeleriniz varsa (belki de bir listeyi sıralamak istersiniz) büyük ölçüde büyük / küçük harf dönüşümü yapmak zorundasınız ve unicode'da büyük harfe göre daha küçük harfli karakterler bulunduğundan, muhtemelen en iyi dönüşüm kullanmak için en iyi dönüşümdür.

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

Javascript, dize karşılaştırmaları için "C" yerel ayarını kullanıyor gibi görünüyor, bu nedenle dizeler ASCII harflerinden başka bir harf içeriyorsa, sonuçlandırma çirkin olacaktır. telleri daha ayrıntılı incelemeksizin bununla ilgili yapılabilecek çok şey yoktur.


7

Biz dize değişkeni bulmak istediğinizi varsayalım needledize değişkeni haystack. Üç gotcha var:

  1. Uluslararası uygulamalar kaçınmalı string.toUpperCaseve string.toLowerCase. Bunun yerine büyük / küçük harf kullanımını yoksayan normal bir ifade kullanın. Örneğin, var needleRegExp = new RegExp(needle, "i");ardından needleRegExp.test(haystack).
  2. Genel olarak, değerini bilmiyor olabilirsiniz needle. needleNormal ifade özel karakterleri içermediğinden emin olun . Bunları kullanarak kaçmak needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");.
  3. Diğer durumlarda, eğer tam olarak eşleştirmek istediğiniz needleve haystacksadece davayı görmezden eklemek için emin olun "^"başında ve "$"normal ifadeniz yapıcı sonunda.

(1) ve (2) maddelerini dikkate alırsak, bir örnek:

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
}

Emin ol! Tek yapmanız gereken tek şey yerini ise new RegExp(...)aşağıdaki doğrultusunda 3 yer: new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");. Bu, arama dizenizden önce veya sonra başka karakter bulunmamasını sağlar needle.
Chris Chute

4

Büyük / küçük harfe duyarlı olmayan karşılaştırmanın iki yolu vardır:

  1. Dizeleri büyük harfe dönüştürün ve katı işleç ( ===) kullanarak bunları karşılaştırın . Sıkı operatör, işlenenlere şu bilgileri okuyarak nasıl davranır: http://www.thesstech.com/javascript/relational-logical-operators
  2. Dize yöntemlerini kullanarak desen eşleştirme:

Büyük / küçük harfe duyarlı olmayan arama için "arama" dizesi yöntemini kullanın. Arama ve diğer dize yöntemleri hakkında bilgi için: 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

Cevaplar burada çok, ama ben String lib genişletme dayalı bir sollution eklemek istiyorum:

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

Bu şekilde Java'da yaptığınız gibi kullanabilirsiniz!

Misal:

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");
}

Çıktı:

"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

Dize eşleşmesi veya karşılaştırması için RegEx kullanın.

JavaScript'te, match()dize karşılaştırması için kullanabilirsiniz i, RegEx yazmayı unutmayın .

Misal:

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

1
Aksi takdirde, kısmi eşleşmelerde iyi olduğunuzdan emin olun matchString.match(/^test$/i).
hackel

Var x = 'test' var küçük harf "test" yerine ne matchString.match(/x/i)işe yarar? Değilse ne işe yarar?
Razvan Zamfir

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

3

Her iki dize de aynı bilinen yerel ayara sahipse, bunun Intl.Collatorgibi bir nesne kullanmak isteyebilirsiniz :

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

Açıkçası, Collatordaha iyi verimlilik için önbelleğe almak isteyebilirsiniz .

Bu yaklaşımın avantajları, RegExps kullanmaktan çok daha hızlı olması ve son derece özelleştirilebilir ( yukarıdaki makalede açıklayıcı localesve optionsyapıcı parametrelerinin açıklamasına bakın) kullanıma hazır harmanlayıcı kümesine dayanmasıdır.


Hassasiyet için bir başka seçenek accentde olay duyarsız tutar, ancak davranır ki, ave áayrı karakterler olarak. Yani baseya accentda tam ihtiyaçlara bağlı olarak her ikisi de uygun olabilir.
Matthew Crumley

2

Bir uzantı yazdım. çok önemsiz

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

1
String # isEqual'ın nasıl çalışması gerektiğine dair farklı fikirlere sahip iki kod tabanı ne olur?
Ryan Cavanaugh

3
@KhanSharp Birçok insan, yerleşik türlerin prototipini değiştirmenin bir anti-desen olduğunu düşünüyor. Bu yüzden insanlar cevabınızı aşağıya çekiyor olabilir.
jt000

1
Bilinmeyen yöntem tanımlarını tercih etmek kötü düşünülmez mi? Örneğin, bazı tarayıcılar uygulamanıza karar verir koymaz String#isEqualya da Object#isEqualtüm sayfalarınız yerel olarak farklı davranır ve şartname sizinkiyle tam olarak eşleşmezse garip şeyler yapabilir.
Robert

2

Bu soru bile çoktan cevap verdi. Ben büyük / küçük harfe duyarlı görmezden RegExp ve maç kullanmak farklı bir yaklaşım var. Lütfen bağlantımı görün 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

İstisnaları atmamaya ve yavaş normal ifadeyi KULLANMAMAYA ne dersiniz?

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

Yukarıdaki snippet, dize boş veya tanımsızsa eşleşmek istemediğinizi varsayar.

Null / undefined ile eşleştirmek istiyorsanız, o zaman:

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

Herhangi bir nedenle undefined vs null değerlerini önemsiyorsanız:

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

Ya da sadecestr1 == str2 || ...
SLaks

1

Hiçbir yanıt açıkça kullanmak için basit bir kod snippet'i sağlamadığından RegExp, girişimim:

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

Birkaç avantajı vardır:

  1. Parametre türünü doğrular ( undefinedörneğin, dize olmayan herhangi bir parametre, gibi bir ifadeyi kilitler str1.toUpperCase()).
  2. Olası uluslararasılaşma sorunlarından muzdarip değildir.
  3. Dizeden kaçar RegExp.

Ama kaçan normal ifade eksikliğinden muzdarip.
Qwertiy

@Qwertiy fair point, stackoverflow.com/a/3561711/67824 başına kaçış eklendi .
Ohad Schneider

0

This is an geliştirilmiş versiyonu arasında bu cevap .

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();
    }
}



Kullanımlar ve testler:


0

Her ikisini de aşağıya dönüştürün (performans nedenleriyle yalnızca bir kez) ve bunları tek bir satırdaki üçlü operatörle karşılaştırın:

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

C'nin öldüğünü kim söyledi? : D
Seth

0

asciiMetinle uğraştığınızı biliyorsanız , sadece büyük / küçük harf ofset karşılaştırması kullanabilirsiniz.

"Mükemmel" dizenizin (eşleşmek istediğiniz dizenin) küçük harfli olduğundan emin olun:

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

Bu kısa steno varyasyonunu seviyorum -

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

Hızlı işlem ve amaçlananı yapar.


0

Bu javascript kütüphane çok sayıda dize işlemi sağlıyor gibi görünüyor. Kullanımı çok uygun

Nasıl kurulur

npm install --save string

İthalat

var S = require('string');

Ignorecase Karşılaştırma Dizesi

var isEqual = S('ignoreCase').equalsIgnoreCase('IGNORECASE')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.