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__

97
localeCompare ()를 사용 하려는 경우 다음과 같이 대소 문자를 구분하지 않는 기능을 사용할 수 있습니다.return a.localeCompare(b, 'en', {'sensitivity': 'base'});
Michael Dyck

2
경우에 따라 기본적으로 전화를 걸지 않은 toLowerCase()경우 +1입니다 localeCompare. 전달할 매개 변수에 대한 자세한 내용은 여기를 참조하십시오. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Milimetric

3
@Milimetric은 참조 된 페이지에 따라 일부 브라우저 (예 : IE <11 또는 Safari)에서 지원하지 않습니다. 여기에 언급 된 솔루션은 매우 좋지만 일부 브라우저의 경우 여전히 백 포트 / 폴리 필이 필요합니다.
3k-

2
배열이 큰 경우 items.sort(new Intl.Collator('en').compare)더 나은 성능 을 위해 사용 하는 것이 좋습니다. ( MDN 참조 )
valtlai

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각 문자열에서 두 번 호출 할 수 있습니다 . 낮은 버전의 문자열을 변수에 저장하는 것이 더 효율적입니다.
Jacob

진실하고 감사합니다. 나는 성능이 아니라 명확성을 염두에두고 이것을 썼다. 나는 그것을 주목해야한다고 생각합니다.
ron tornambe

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
아무것도 필요

47

이 오래된 질문을 다시 볼 때입니다.

의존하는 솔루션을 사용해서는 안됩니다 toLowerCase. 그들은이다 비효율적 간단하게 작동하지 않는 일부 언어 (예를 들어 터키어)에서. 이것을 선호하십시오 :

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

브라우저 호환성에 대한 설명서 를 확인하고 sensitivity옵션 에 대한 모든 정보 를 확인하십시오 .


1
모든 자바 스크립트 엔진에서 지원되는 것은 아닙니다.
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
또는return a === b ? 0 : a > b ? 1 : -1;
Devin G Rhode

숫자를 나타내는 문자열 에는 의도 한대로 작동하지 않을 수 있습니다. 산술 연산자는 문자열 대신 숫자의 의미를 사용합니다. 예를 들어 ["111", "33"], ["111", "33"]문자 코드 순서에서 1이 3보다 앞에 오므 로 반환해야 할 수 있습니다 . 그러나 ["33", "111"]number 33이 number 보다 작기 때문에이 답변의 함수가 반환됩니다 111.
오스틴 데이비스

@AustinDavis "33" > "111" === true33 > 111 === false. 의도 한대로 작동합니다.
어둠의 절대자 니엣

12

새로운 Intl.Collator().compareMDN을 사용하여 배열을 정렬 할 때 더 효율적 입니다. 단점은 이전 브라우저에서 지원하지 않는다는 것입니다. MDN은 Safari에서 전혀 지원되지 않는다고 말합니다. Intl.Collator지원됨을 나타내므로 확인해야합니다 .

큰 배열 정렬과 같이 많은 수의 문자열을 비교할 때는 Intl.Collator 객체를 만들고 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 연산자는 일반적으로 할당이있는 경우 짧은 형식의 '삼항 연산자'입니다.
? :를 옆으로 보면 Elvis처럼 보입니다
.

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

당신이 사용할 수있는:

x = y?1:2;

즉, y가 참이면 1 (x에 대입)을 반환하고, 그렇지 않으면 2 (x에 대입)를 반환합니다.


5
놀랍게도 이것은 엘비스 운영자가 아닙니다. 이것은 기본적인 삼항 연산자입니다. 진정한 Elvis 연산자는 null-coalescing입니다. 예를 들어 대신에 x = y ? y : z할 수 있습니다 x = y ?: z. Javascript에는 실제 Elvis 연산자가 없지만 x = y || z비슷한 방식으로 사용할 수 있습니다 .
찰스 우드

3

다른 답변은 배열에 문자열이 있다고 가정합니다. 배열에 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"이전에 정렬되었습니다
MattW

내가 정의를 찾은 것 같아요 Array.prototype.sort: | 왜냐하면 (''+notdefined) === "undefined" 실제로 부분 사실 이기 때문 입니다. 즉, sort 함수에서 -1과 1을 뒤집어 순서를 바꾸면 정의되지 않은 여전히 ​​끝까지 정렬됩니다. 배열 정렬 컨텍스트 외부에서 비교 함수를 사용할 때도 고려해야합니다 (이 질문에 왔을 때와 마찬가지로).
MattW

그리고 이제 그 Array.prototype.sort정의에 대해 깊이 생각해 보았습니다 . 첫째, 요소를 compareFn에 전달하기 전에 (''+a)ECMAScript toString()를 호출 할 필요 가 없습니다. 둘째, 동일한 (대소 문자를 포함하여) 문자열을 비교할 때 ignoreCase반환 된다는 사실 1은 중복 값이있는 경우 사양이 결과를 정의하지 않는다는 것을 의미합니다 (필요하지 않은 스왑이 발생해도 괜찮을 것입니다).
MattW

@MattW, 그것은 x x <undefined 및 x> undefined 모두 false 인undefined 특별한 경우 인 것 같습니다 . 그것은 항상 마지막이며, 정렬 구현의 부산물입니다. ( ''+ a)를 단순히 a로 변경하려고 시도했지만 실패합니다. 나는 얻는다 . 분명히 되어 있지 compareFn를 호출하기 전에했다. undefinedTypeError: a.toUpperCase is not a functiontoString
존 헨켈

1
아, 알겠습니다. 들어 undefinedcompareFn이됩니다 호출되지 않습니다
존 헨켈


1

허용 된 답변을 지원하기 위해 아래 함수가 원래 배열의 값을 정렬하여 변경하여 소문자를 정렬 할뿐만 아니라 대문자 값도 소문자로 변경한다고 덧붙이고 싶습니다. 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());
});

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]가 되려면 두 개의 소문자 값이 같을 때 다시 비교해야합니다.

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 ()를 호출 할 수 있도록 최고 답변을 polyfill로 감쌌습니다.

// 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 2016 년

-2

에 줄을 싸십시오 / /i. 이것은 정규식을 사용하여 케이싱을 무시하는 쉬운 방법입니다.


문제는 정렬이 아니라 일치에 관한 것입니다.
user4642212
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.