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/en-US/docs/Web/JavaScript/Reference/…
myArray.sort(
function(a, b) {
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return 1;
return 0;
}
);
편집 : 나는 원래 성능을 염두에두기보다는 기술을 설명하기 위해 이것을 썼습니다. 보다 컴팩트 한 솔루션에 대해서는 @Ivan Krechetov의 답변을 참조하십시오.
toLowerCase
각 문자열에서 두 번 호출 할 수 있습니다 . 낮은 버전의 문자열을 변수에 저장하는 것이 더 효율적입니다.
.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'}))
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"]
문자 코드 순서에서 1이 3보다 앞에 오므 로 반환해야 할 수 있습니다 . 그러나 ["33", "111"]
number 33
이 number 보다 작기 때문에이 답변의 함수가 반환됩니다 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 연산자는 일반적으로 할당이있는 경우 짧은 형식의 '삼항 연산자'입니다.
? :를 옆으로 보면 Elvis처럼 보입니다
.
if (y) {
x = 1;
} else {
x = 2;
}
당신이 사용할 수있는:
x = y?1:2;
즉, y가 참이면 1 (x에 대입)을 반환하고, 그렇지 않으면 2 (x에 대입)를 반환합니다.
x = y ? y : z
할 수 있습니다 x = y ?: z
. Javascript에는 실제 Elvis 연산자가 없지만 x = y || z
비슷한 방식으로 사용할 수 있습니다 .
다른 답변은 배열에 문자열이 있다고 가정합니다. 배열에 null, undefined 또는 기타 문자열이 아닌 경우에도 작동하기 때문에 내 방법이 더 좋습니다.
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"
실제로 부분 이 사실 이기 때문 입니다. 즉, sort 함수에서 -1과 1을 뒤집어 순서를 바꾸면 정의되지 않은 여전히 끝까지 정렬됩니다. 배열 정렬 컨텍스트 외부에서 비교 함수를 사용할 때도 고려해야합니다 (이 질문에 왔을 때와 마찬가지로).
Array.prototype.sort
정의에 대해 깊이 생각해 보았습니다 . 첫째, 요소를 compareFn에 전달하기 전에 (''+a)
ECMAScript toString()
를 호출 할 필요 가 없습니다. 둘째, 동일한 (대소 문자를 포함하여) 문자열을 비교할 때 ignoreCase
반환 된다는 사실 1
은 중복 값이있는 경우 사양이 결과를 정의하지 않는다는 것을 의미합니다 (필요하지 않은 스왑이 발생해도 괜찮을 것입니다).
undefined
특별한 경우 인 것 같습니다 . 그것은 항상 마지막이며, 정렬 구현의 부산물입니다. ( ''+ a)를 단순히 a로 변경하려고 시도했지만 실패합니다. 나는 얻는다 . 분명히 되어 있지 compareFn를 호출하기 전에했다. undefined
TypeError: a.toUpperCase is not a function
toString
undefined
compareFn이됩니다 호출되지 않습니다
ES6 버전 :
["Foo", "bar"].sort((a, b) => a.localeCompare(b, 'en', { sensitivity: 'base' }))
허용 된 답변을 지원하기 위해 아래 함수가 원래 배열의 값을 정렬하여 변경하여 소문자를 정렬 할뿐만 아니라 대문자 값도 소문자로 변경한다고 덧붙이고 싶습니다. Mary 옆에서 Mary를보고 싶지만 Mary의 첫 번째 값이 소문자로 변경되기를 원하지 않기 때문에 이것은 나에게 문제가됩니다.
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]가 되려면 두 개의 소문자 값이 같을 때 다시 비교해야합니다.
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 ()를 호출 할 수 있도록 최고 답변을 polyfill로 감쌌습니다.
// Array.sortIgnoreCase() polyfill
if (!Array.prototype.sortIgnoreCase) {
Array.prototype.sortIgnoreCase = function () {
return this.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
};
}