JavaScriptで並べ替える必要がある文字列の配列がありますが、大文字と小文字は区別されません。これを実行するには?
JavaScriptで並べ替える必要がある文字列の配列がありますが、大文字と小文字は区別されません。これを実行するには?
回答:
(ほぼ:)ワンライナー
["Foo", "bar"].sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
その結果
[ 'bar', 'Foo' ]
ながら
["Foo", "bar"].sort();
結果は
[ 'Foo', 'bar' ]
return a.localeCompare(b, 'en', {'sensitivity': 'base'});
toLowerCase()
ときに+1を呼び出さないlocaleCompare
こと。渡すパラメーターの詳細については、developer.mozilla.org
items.sort(new Intl.Collator('en').compare)
パフォーマンスを向上させるために使用するのが理にかなっています。(MDNを参照してください。)
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
編集: 私が最初にこれを書いたのは、パフォーマンスを念頭に置くのではなく、テクニックを説明するためであることに注意してください。よりコンパクトなソリューションについては、回答@Ivan Krechetovも参照してください。
toLowerCase
各文字列で2回呼び出すことができます。変数に文字列の下位バージョンを格納する方が効率的です。
.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
この古い質問を再訪する時が来ました。
に依存するソリューションは使用しないでくださいtoLowerCase
。それらは非効率的で、一部の言語(たとえば、トルコ語)では機能しません。これを好む:
['Foo', 'bar'].sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))
ブラウザの互換性についてドキュメントを確認し、sensitivity
オプションについて知っておくべきことはすべてあります。
arr.sort(function(a,b) {
a = a.toLowerCase();
b = b.toLowerCase();
if (a == b) return 0;
if (a > b) return 1;
return -1;
});
return a === b ? 0 : a > b ? 1 : -1;
["111", "33"]
それを返す["111", "33"]
ことができます。ただし、["33", "111"]
数値33
が数値より小さいため、この回答の関数は戻り111
ます。
"33" > "111" === true
および33 > 111 === false
。意図したとおりに機能します。
新しいを使用することもできますIntl.Collator().compare
。MDNごとに、配列をソートする際により効率的です。欠点は、古いブラウザではサポートされていないことです。MDNによると、Safariではまったくサポートされていません。Intl.Collator
サポートされていると記載されているため、確認する必要があります。
大きな配列の並べ替えなど、多数の文字列を比較する場合は、Intl.Collatorオブジェクトを作成して、compareプロパティによって提供される関数を使用することをお勧めします
["Foo", "bar"].sort(Intl.Collator().compare); //["bar", "Foo"]
入力配列の要素の順序に関係なく同じ順序を保証したい場合は、安定した並べ替えを以下に示します。
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;
});
でケースを正規化.sort()
し.toLowerCase()
ます。
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への割り当て)を返します。
x = y ? y : z
ですx = y ?: z
。たとえば、の代わりにを実行できます。JavaScriptには実際のElvisオペレーターはありませんが、x = y || z
同様の方法で使用できます。
他の回答では、配列に文字列が含まれていると想定しています。配列に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」の前にソートされる
Array.prototype.sort
:| なぜなら、(''+notdefined) === "undefined"
実際のところは真実だからです...つまり、並べ替え関数で-1と1を入れ替えて順序を逆にしても、未定義の場合は最後まで並べ替えられます。また、配列ソートのコンテキスト外で比較関数を使用する場合も考慮する必要があります(この質問に出会ったときのように)。
Array.prototype.sort
定義を熟考しました-より多くのコメント。まず、必要はありません。compareFnに渡す前に、要素で(''+a)
ECMAScript toString()
を呼び出す必要があります。第2に、等しい(大文字の場合を含む)文字列を比較したときにignoreCase
返さ1
れるという事実は、重複する値がある場合、仕様が結果を定義しないことを意味します(おそらく、不要なスワップが発生するだけで結構です)。
undefined
は特別なケースであるように思われます。これはどのxに対しても x <undefinedとx> undefinedはどちらもfalseです。これundefined
は常に最後です。sortのsort実装の副産物です。( '' + a)を単にaに変更しようとしましたが、失敗しました。私は得るTypeError: a.toUpperCase is not a function
。どうやらtoString
されていない compareFnを呼び出す前に呼び出されます。
undefined
compareFnがされて呼び出されることはありません
ES6バージョン:
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
ソース:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
受け入れられた答えをサポートするために、以下の関数がソートされる元の配列の値を変更し、小文字だけでなく大文字の値も小文字に変更されるように追加したいと思います。メアリーをメアリーの隣に表示したいのですが、最初の値のメアリーのケースを小文字に変更したくないので、これは私にとって問題です。
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());
});
これは、理解に苦労している場合に役立ちます。
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.
***/
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;
}
}
}
文字列配列で.sortIgnoreCase()を呼び出すことができるように、トップの回答をポリフィルで囲みました
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}