JavaScript'te büyük / küçük harfe duyarlı olmayan sıralama nasıl yapılır?


Yanıtlar:


404

İçinde (neredeyse :) bir astar

["Foo", "bar"].sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
});

Hangi sonuçlar

[ 'bar', 'Foo' ]

Süre

["Foo", "bar"].sort();

sonuç

[ 'Foo', 'bar' ]

9
LocaleCompare'nin gelişmiş seçeneklerinin henüz tüm platformlarda / tarayıcılarda desteklenmediğini unutmayın. Bu örnekte kullanılmadıklarını biliyorum, ama sadece netlik eklemek istedim. Daha fazla bilgi için MDN'ye bakınız
Ayame__

97
Eğer localeCompare () dahil etmek gidiyoruz, sadece kullanabilirsiniz onun küçük harf duyarsız olmak için yeteneği örn:return a.localeCompare(b, 'en', {'sensitivity': 'base'});
Michael Dyck

2
Çağırmak için değil 1 toLowerCase()zaman localeComparezaten bazı durumlarda varsayılan olarak bunu yapıyor. Buradan geçirilecek parametreler hakkında daha fazla bilgiyi buradan edinebilirsiniz: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Milimetrik

3
@Milimetrik başvurulan sayfaya göre, bu özellik bazı tarayıcılar tarafından desteklenmez (örn. IE <11 veya Safari). burada bahsedilen çözüm çok iyi, ancak yine de bazı tarayıcılar için backporting / polyfill gerektirir.
3k-

2
Geniş bir diziniz varsa, items.sort(new Intl.Collator('en').compare)daha iyi performans için kullanmak mantıklıdır . (Bkz. MDN .)
valtlai

60
myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

DÜZENLEME: Lütfen bunu aklınızda performans göstermek yerine tekniği göstermek için yazdığımı unutmayın. Daha kompakt bir çözüm için lütfen @Ivan Krechetov'a bakınız.


3
Bu, toLowerCaseher dizede iki kez çağırabilir ; dizenin indirgenmiş sürümlerinde değişkenler için daha verimli olur.
Jacob

Doğru ve teşekkürler. Bunu performansla değil, netlikle yazdım. Sanırım bunu not etmeliyim.
ron tornambe

1
@Jacob Adil olmak gerekirse, kabul edilen cevabın aynı temel sorunu vardır: muhtemelen .toLowerCase()dizideki her öğe için birden çok kez çağırabilir . Örneğin, 10 öğeyi ters sırada sıralarken 45 karşılaştırma işlevini çağırır. var i = 0; ["z","y","x","w","v","u","t","s","r","q"].sort(function (a, b) {++i; return a.toLowerCase().localeCompare(b.toLowerCase());}); console.log("Calls to Compare: " + i); // i === 45
hiçbir şey gerekli değil

47

Bu eski soruyu tekrar ziyaret etmenin zamanı geldi.

Güvenilir çözümler kullanmamalısınız toLowerCase. Bunlar verimsiz ve basitçe çalışmayan bazı diller (örneğin Türkçe) içinde. Bunu tercih et:

['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))

Tarayıcı uyumluluğu için belgelere bakın ve sensitivityseçenek hakkında bilinmesi gerekenler.


1
Dikkatli olun, bu tüm javascript motorlarında desteklenmez.
Luboš Turek

26
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if (a == b) return 0;
    if (a > b) return 1;
    return -1;
});

1
veyareturn a === b ? 0 : a > b ? 1 : -1;
Devin G Rhode

Bu, sayıları temsil eden dizeler için tasarlandığı gibi çalışmayacaktır . Aritmetik işleçler, dize yerine sayıların anlambilimini kullanır. Eğer varsa ["111", "33"], geri dönmesini isteyebiliriz, ["111", "33"]çünkü 1 karakter kodu sıralamasında 1 önce gelir. Ancak, bu ["33", "111"]sayıdaki işlev , sayı sayıdan 33küçük olduğu için geri döner 111.
Austin Davis

@AustinDavis "33" > "111" === trueve 33 > 111 === false. İstendiği gibi çalışır.
Niet the Dark Absol

12

Yeni Intl.Collator().compareolanı da kullanabilirsiniz , her MDN için dizileri sıralarken daha verimlidir . Dezavantajı, eski tarayıcılar tarafından desteklenmemesidir. MDN, Safari'de hiç desteklenmediğini belirtir. Intl.CollatorDesteklendiğini belirttiği için doğrulamanız gerekiyor .

Büyük dizileri sıralama gibi çok sayıda dizeyi karşılaştırırken, bir Intl.Collator nesnesi oluşturmak ve compar özelliği tarafından sağlanan işlevi kullanmak daha iyidir

["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]

11

Giriş dizisindeki öğelerin sırasından bağımsız olarak aynı sırayı garanti etmek istiyorsanız, kararlı bir sıralama:

myArray.sort(function(a, b) {
    /* Storing case insensitive comparison */
    var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
    /* If strings are equal in case insensitive comparison */
    if (comparison === 0) {
        /* Return case sensitive comparison instead */
        return a.localeCompare(b);
    }
    /* Otherwise return result */
    return comparison;
});

5

Davayı Normale .sort()ile .toLowerCase().


4

Elvis operatörünü de kullanabilirsiniz:

arr = ['Bob', 'charley', 'fudge', 'Fudge', 'biscuit'];
arr.sort(function(s1, s2){
    var l=s1.toLowerCase(), m=s2.toLowerCase();
    return l===m?0:l>m?1:-1;
});
console.log(arr);

verir:

biscuit,Bob,charley,fudge,Fudge

LocaleCompare yöntemi muhtemelen iyi ...

Not: Elvis operatörü, genellikle ödevle birlikte, başka bir durumda kısa bir 'üçlü operatör' şeklindedir.
?: Yana bakarsanız, Elvis gibi görünür ...
yani:

if (y) {
  x = 1;
} else {
  x = 2;
}

kullanabilirsiniz:

x = y?1:2;

yani y doğru olduğunda, 1 değerini (x'e atama için), aksi takdirde 2'yi (x'e atama için) döndürün.


5
Bilgiçlikçi olmak için, bu Elvis operatörü değil. Bu sadece temel bir üçlü operatör. Gerçek bir Elvis operatörü boş değerdedir, örneğin x = y ? y : zbunu yapabilirsiniz x = y ?: z. Javascript'in gerçek bir Elvis operatörü yok, ancak x = y || zbenzer bir şekilde kullanabilirsiniz.
Charles Wood

3

Diğer yanıtlar dizinin dize içerdiğini varsayar. Benim yöntem daha iyidir, çünkü dizi null, undefined veya diğer dizeler içermese bile çalışacaktır.

var notdefined;
var myarray = ['a', 'c', null, notdefined, 'nulk', 'BYE', 'nulm'];

myarray.sort(ignoreCase);

alert(JSON.stringify(myarray));    // show the result

function ignoreCase(a,b) {
    return (''+a).toUpperCase() < (''+b).toUpperCase() ? -1 : 1;
}

null'Nulk' ve 'nulm' arasında sıralanır. Ama undefinedolacak hep en son sıralanır.


(''+notdefined) === "undefined"yani "z" den önce
sıralanır

Sanırım tanımını aramalıydım Array.prototype.sort: | çünkü (''+notdefined) === "undefined" gerçekten doğru olan kısım doğrudur ... yani, sırayı tersine çevirmek için sıralama işlevinde -1 ve 1'i çevirirseniz, tanımsız yine de sonuna kadar sıralar. Ayrıca, bir sıralama dizisi bağlamının dışında karşılaştırma işlevini kullanırken de dikkate alınması gerekir (bu soruya geldiğimde olduğu gibi).
MattW

Ve şimdi bu Array.prototype.sorttanımı düşünerek - birkaç yorum daha. İlk olarak, (''+a)- ECMAScript toString()öğesinin CompareFn'ye geçirilmeden önce çağrılması gerekmez. İkincisi, eşit (durum için eşit-ancak-dahil) dizeleri karşılaştırırken ignoreCasegeri 1dönmesi, belirtimin yinelenen değerler varsa sonucu tanımlamaması anlamına gelir (muhtemelen bazı gereksiz takaslarla iyi olacaktır, sanırım).
MattW

@MattW, Bana öyle geliyor ki undefined, herhangi bir x x <undefined ve x> undefined için ikisi de yanlış . Bu undefinedher zaman sonuncudur, sıralama türünün bir yan ürünüdür. ('' + A) 'yı basitçe a olarak değiştirmeye çalıştım, ancak başarısız oluyor. Anladım TypeError: a.toUpperCase is not a function. Görünüşe toStringedilir değil compareFn aramadan önce aradı.
John Henckel

1
Ah, tamam, bu çok mantıklı. Karşılaştırma için undefinedFn asla çağrılmaz
John Henckel


1

Kabul edilen cevabı desteklemek için, aşağıdaki fonksiyonun orijinal dizideki değerleri sıralanacak şekilde değiştirdiğini eklemek istiyorum, böylece sadece küçük harf sıralamakla kalmayacak, aynı zamanda büyük harf değerleri de küçük harfe dönüştürülecektir. Bu benim için bir sorun, çünkü Mary'yi mary'nin yanında görmek istememe rağmen, Mary'nin ilk değeri vakasının küçük harfe değiştirilmesini istemiyorum.

myArray.sort(
  function(a, b) {
    if (a.toLowerCase() < b.toLowerCase()) return -1;
    if (a.toLowerCase() > b.toLowerCase()) return 1;
    return 0;
  }
);

Deneylerimde, kabul edilen yanıttan aşağıdaki işlev doğru şekilde sıralanır, ancak değerleri değiştirmez.

["Foo", "bar"].sort(function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
});

0

Anlamak için mücadele ettiyseniz, bu yardımcı olabilir:

var array = ["sort", "Me", "alphabetically", "But", "Ignore", "case"];
console.log('Unordered array ---', array, '------------');

array.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    console.log("Compare '" + a + "' and '" + b + "'");

    if( a == b) {
        console.log('Comparison result, 0 --- leave as is ');
        return 0;
    }
    if( a > b) {
        console.log('Comparison result, 1 --- move '+b+' to before '+a+' ');
        return 1;
    }
    console.log('Comparison result, -1 --- move '+a+' to before '+b+' ');
    return -1;


});

console.log('Ordered array ---', array, '------------');


// return logic

/***
If compareFunction(a, b) is less than 0, sort a to a lower index than b, i.e. a comes first.
If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.
If compareFunction(a, b) is greater than 0, sort b to a lower index than a.
***/

http://jsfiddle.net/ianjamieson/wmxn2ram/1/


0
arr.sort(function(a,b) {
    a = a.toLowerCase();
    b = b.toLowerCase();
    if( a == b) return 0;
    if( a > b) return 1;
    return -1;
});

Yukarıdaki fonksiyonda, sadece küçük harf a ve b değeri ne zaman karşılaştırırsak, güzel bir sonuç elde edemeyiz.

Örneğin, dizi [A, a, B, b, c, C, D, d, e, E] ise ve yukarıdaki işlevi kullanırsak, tam olarak bu diziye sahibiz. Hiçbir şey değişmedi.

Sonucun [A, a, B, b, C, c, D, d, E, e] olması için, iki küçük harf değeri eşit olduğunda tekrar karşılaştırmalıyız:

function caseInsensitiveComparator(valueA, valueB) {
    var valueALowerCase = valueA.toLowerCase();
    var valueBLowerCase = valueB.toLowerCase();

    if (valueALowerCase < valueBLowerCase) {
        return -1;
    } else if (valueALowerCase > valueBLowerCase) {
        return 1;
    } else { //valueALowerCase === valueBLowerCase
        if (valueA < valueB) {
            return -1;
        } else if (valueA > valueB) {
            return 1;
        } else {
            return 0;
        }
    }
}

-1

Ben dize diziler üzerinde .sortIgnoreCase () çağırabilirsiniz böylece bir çoklu doldurma üst yanıt sarılmış

// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
    Array.prototype.sortIgnoreCase = function () {
        return this.sort(function (a, b) {
            return a.toLowerCase().localeCompare(b.toLowerCase());
        });
    };
}

Lütfen bunu asla yapma. Yalnızca sahip olduğunuz şeylerin prototipini değiştirin. Bu Array yöntemi ECMAScript teknik özelliklerinde hiçbir yerde olmadığından, bu bir çoklu dolgu değildir.
Joe Maffei

-2

Dizelerinizi sarın / /i. Bu, kasayı yoksaymak için normal ifadeyi kullanmanın kolay bir yoludur


Soru sıralama ile ilgilidir, eşleştirme değil.
user4642212
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.