JavaScriptで大文字と小文字を区別しない並べ替えを実行するにはどうすればよいですか?


回答:


404

(ほぼ:)ワンライナー

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

その結果

[ 'bar', 'Foo' ]

ながら

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

結果は

[ 'Foo', 'bar' ]

9
localeCompareの詳細オプションは、まだすべてのプラットフォーム/ブラウザでサポートされているわけではないことに注意してください。この例では使用されていませんが、わかりやすくするために追加したかっただけです。詳細についてはMDNを参照してください
Ayame__ 2014年

97
あなたがlocaleCompareを()関与するつもりなら、あなただけ使用することができ、その大文字と小文字を区別しない、する能力を例えば:return a.localeCompare(b, 'en', {'sensitivity': 'base'});
マイケル・ダイク

2
場合によっては、デフォルトですでにそれを行っているtoLowerCase()ときに+1を呼び出さないlocaleCompareこと。渡すパラメーターの詳細については、developer.mozilla.org
en

3
@Milimetricは参照ページと一致し、その機能は一部のブラウザー(IE <11またはSafariなど)でサポートされていません。ここで説明する解決策は非常に優れていますが、一部のブラウザではバックポート/ポリフィルが必要です。
3k- 2015

2
大きな配列がある場合は、items.sort(new Intl.Collator('en').compare)パフォーマンスを向上させるために使用するのが理にかなっています。(MDNを参照してください。)
valtlai 2018

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

編集: 私が最初にこれを書いたのは、パフォーマンスを念頭に置くのではなく、テクニックを説明するためであることに注意してください。よりコンパクトなソリューションについては、回答@Ivan Krechetovも参照してください。


3
これはtoLowerCase各文字列で2回呼び出すことができます。変数に文字列の下位バージョンを格納する方が効率的です。
ジェイコブ

真実と感謝。これは、パフォーマンスではなく明確に念頭に置いて作成しました。私はそれに注意する必要があると思います。
ron tornambe 2013

1
@Jacob公平に言うと、受け入れられた回答には同じ基本的な問題があります.toLowerCase()。配列内の各項目に対して複数回呼び出す可能性があります。たとえば、10個のアイテムを逆順にソートする場合、45は比較関数を呼び出します。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
2016

47

この古い質問を再訪する時が来ました。

に依存するソリューションは使用しないでくださいtoLowerCase。それらは非効率的で、一部の言語(たとえば、トルコ語)では機能ません。これを好む:

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

ブラウザの互換性についてドキュメントを確認し、sensitivityオプションについて知っておくべきことはすべてあります。


1
これは、すべてのJavaScriptエンジンでサポートされているわけではないので注意してください。
Lubošトゥレク

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
またはreturn a === b ? 0 : a > b ? 1 : -1;
Devin G Rhode

これは、数値を表す文字列に対して意図したとおりに機能ない可能性があります。算術演算子は、文字列ではなく数値のセマンティクスを使用します。たとえば、がある場合は、文字コードの順序付けで1が3の前に来るので、["111", "33"]それを返す["111", "33"]ことができます。ただし、["33", "111"]数値33が数値より小さいため、この回答の関数は戻り111ます。
オースティンデイビス

@AustinDavis "33" > "111" === trueおよび33 > 111 === false。意図したとおりに機能します。
Niet the Dark Absol

12

新しいを使用することもできますIntl.Collator().compare。MDNごとに、配列をソートする際により効率的です。欠点は、古いブラウザではサポートされていないことです。MDNによると、Safariではまったくサポートされていません。Intl.Collatorサポートされていると記載されているため、確認する必要があります。

大きな配列の並べ替えなど、多数の文字列を比較する場合は、Intl.Collat​​orオブジェクトを作成して、compareプロパティによって提供される関数を使用することをお勧めします

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

11

入力配列の要素の順序に関係なく同じ順序を保証したい場合は、安定した並べ替えを以下に示します。

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

でケースを正規化.sort().toLowerCase()ます。


4

Elvis演算子を使用することもできます。

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

与える:

biscuit,Bob,charley,fudge,Fudge

localeCompareメソッドはおそらく問題ありません...

注:Elvis演算子は、それ以外の場合、通常は代入を使用する場合の短縮形の「3項演算子」です。
?:を横に見ると、エルビスのように見えます...
つまり、次の代わりに:

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

あなたは使うことができます:

x = y?1:2;

つまり、yがtrueの場合は1(xへの割り当て)を返し、そうでない場合は2(xへの割り当て)を返します。


5
教訓的に言えば、これはエルビスのオペレーターではありません。これは基本的な三項演算子です。真のエルビス演算子はnull結合x = y ? y : zですx = y ?: z。たとえば、の代わりにを実行できます。JavaScriptには実際のElvisオペレーターはありませんが、x = y || z同様の方法で使用できます。
チャールズウッド、

3

他の回答では、配列に文字列が含まれていると想定しています。配列にnull、未定義、またはその他の非文字列が含まれている場合でも機能するため、私の方法の方が優れています。

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」と「nulm」の間にソートされます。しかし、undefinedされます常に最後にソート。


(''+notdefined) === "undefined"「z」の前にソートされる
MattW

の定義を調べたほうがいいと思いますArray.prototype.sort:| なぜなら、(''+notdefined) === "undefined" 実際のところは真実だからです...つまり、並べ替え関数で-1と1を入れ替えて順序を逆にしても、未定義の場合は最後まで並べ替えられます。また、配列ソートのコンテキスト外で比較関数を使用する場合も考慮する必要があります(この質問に出会ったときのように)。
MattW

そして今、そのArray.prototype.sort定義を熟考しました-より多くのコメント。まず、必要はありません。compareFnに渡す前に、要素で(''+a)ECMAScript toString()を呼び出す必要があります。第2に、等しい(大文字の場合を含む)文字列を比較したときにignoreCase返さ1れるという事実は、重複する値がある場合、仕様が結果を定義しないことを意味します(おそらく、不要なスワップが発生するだけで結構です)。
MattW

@MattW、それundefinedは特別なケースであるように思われます。これはどのxに対して x <undefinedとx> undefinedはどちらもfalseです。これundefinedは常に最後です。sortのsort実装の副産物です。( '' + a)を単にaに変更しようとしましたが、失敗しました。私は得るTypeError: a.toUpperCase is not a function。どうやらtoStringされていない compareFnを呼び出す前に呼び出されます。
ジョンヘンケル2016

1
ああ、わかりました、それは完全に理にかなっています。undefinedcompareFnがされて呼び出されることはありません
ジョン・ヘンケル


1

受け入れられた答えをサポートするために、以下の関数がソートされる元の配列の値を変更し、小文字だけでなく大文字の値も小文字に変更されるように追加したいと思います。メアリーをメアリーの隣に表示したいのですが、最初の値のメアリーのケースを小文字に変更したくないので、これは私にとって問題です。

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

私の実験では、受け入れられた回答の次の関数は正しくソートされますが、値は変更されません。

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

0

これは、理解に苦労している場合に役立ちます。

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

上記の関数で、小文字の2つの値aとbを比較すると、きれいな結果が得られません。

たとえば、配列が[A、a、B、b、c、C、D、d、e、E]で、上記の関数を使用すると、その配列が正確に得られます。何も変わっていません。

結果が[A、a、B、b、C、c、D、d、E、e]になるには、2つの小文字の値が等しい場合にもう一度比較する必要があります。

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

文字列配列で.sortIgnoreCase()を呼び出すことができるように、トップの回答をポリフィルで囲みました

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

これを絶対にしないでください。所有するもののプロトタイプのみを変更します。このArrayメソッドはECMAScript仕様のどこにもないため、これもポリフィルではありません。
Joe Maffei

-2

文字列をで囲みます/ /i。これは、正規表現を使用して大文字小文字を無視する簡単な方法です


問題は、一致ではなく、ソートについてです。
user4642212 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.