[javascript] JavaScript에서 문자열을 정렬하는 방법

attr문자열 유형 의 필드 를 기준으로 정렬하려는 객체 목록이 있습니다 . 나는 사용하려고-

list.sort(function (a, b) {
    return a.attr - b.attr
})

하지만 발견 -자바 스크립트 문자열 작업에 표시되지 않습니다. 문자열 유형의 속성을 기반으로 객체 목록을 정렬하려면 어떻게해야합니까?



답변

String.prototype.localeCompare귀하의 예를 사용하십시오 :

list.sort(function (a, b) {
    return ('' + a.attr).localeCompare(b.attr);
})

예외를 피하기 위해 a.attr을 문자열로 만듭니다. Internet Explorer 6 및 Firefox 1 부터localeCompare 지원되었습니다 . 로캘과 관련이없는 다음 코드가 사용 된 것을 볼 수도 있습니다.

if (item1.attr < item2.attr)
  return -1;
if ( item1.attr > item2.attr)
  return 1;
return 0;


답변

업데이트 된 답변 (2014 년 10 월)

나는이 문자열 자연 정렬 순서에 대해 정말로 화가 났기 때문에이 문제를 조사하는 데 꽤 시간이 걸렸습니다. 이게 도움이 되길 바란다.

긴 이야기 짧음

localeCompare()문자 지원이 잘못되었습니다. 그냥 사용하십시오. 에서 지적한 것처럼 Shog9귀하의 질문에 대한 답변은 다음과 같습니다.

return item1.attr.localeCompare(item2.attr);

모든 사용자 정의 자바 스크립트 “자연 문자열 정렬 순서”구현에서 발견 된 버그

“자연 문자열 정렬 순서”라고하는 더 정확하게 문자열 비교를 시도하는 많은 사용자 정의 구현이 있습니다.

이러한 구현으로 “재생”할 때 항상 이상한 “자연 정렬 순서”선택 또는 실수 (또는 최상의 경우 생략)를 발견했습니다.

일반적으로 특수 문자 (공백, 대시, 앰퍼샌드, 괄호 등)는 올바르게 처리되지 않습니다.

그런 다음 다른 위치에 혼합되어 나타나는 것으로 나타났습니다. 일반적으로 다음과 같습니다.

  • 일부는 대문자 ‘Z’와 소문자 ‘a’사이에 있습니다.
  • 일부는 ‘9’와 대문자 ‘A’사이에 있습니다.
  • 일부는 소문자 ‘z’뒤에 올 것입니다

공백 문자를 제외하고 특수 문자가 모두 한곳에서 “그룹화”될 것으로 예상 한 경우 (항상 첫 문자 임). 즉, 숫자 앞 또는 숫자와 문자 사이의 모든 문자 (소문자와 대문자는 “함께”함께 “)이거나 문자 뒤에 있습니다.

내 결론은 간신히 특이한 문자 (예 : 대시, 느낌표 등의 발음 부호가있는 문자)를 추가하기 시작할 때 모두 일관성있는 순서를 제공하지 못한다는 것입니다.

맞춤형 구현에 대한 연구 :

를 통해 브라우저의 기본 “자연 문자열 정렬 순서”구현 localeCompare()

localeCompare()가장 오래된 구현 (로캘 및 옵션 인수가없는)은 IE6 +에서 지원됩니다. http://msdn.microsoft.com/en-us/library/ie/s4esdbwz (v = vs.94) .aspx (localeCompare ( ) 방법). 내장 된 localeCompare()방법은 국제 및 특수 문자까지 정렬에서 훨씬 더 잘 작동합니다. 이 localeCompare()방법을 사용하는 유일한 문제점 은 “사용 된 로케일 및 정렬 순서가 전적으로 구현에 의존적”이라는 것입니다. 즉, stringOne.localeCompare (stringTwo)와 같은 localeCompare를 사용하는 경우 : Firefox, Safari, Chrome 및 IE는 문자열의 정렬 순서가 다릅니다.

브라우저 고유 구현에 대한 연구 :

“문자열 자연 정렬 순서”의 어려움

견고한 알고리즘을 구현하는 것 (즉, 일관성은 있지만 광범위한 문자를 포함 함)은 매우 어려운 작업입니다. UTF8은 포함 2000 개 이상의 문자커버 120 명 이상의 스크립트 (언어) . 마지막으로이 작업에 대한 일부 사양이 있으며 “Unicode Collation Algorithm”이라고하며 http://www.unicode.org/reports/tr10/에 있습니다. /software/257286/is-there-any-language-agnostic-specification-for-string-natural-sorting-order에 게시 된이 질문에 대한 자세한 내용을 찾을 수 있습니다

최종 결론

따라서 내가 만난 자바 스크립트 사용자 정의 구현에서 제공하는 현재 수준의 지원을 고려할 때 아마도이 모든 문자 및 스크립트 (언어)를 지원하는 데 아무런 도움이되지 않을 것입니다. 따라서 브라우저의 기본 localeCompare () 메서드를 사용하고 싶습니다. 그렇습니다. 브라우저에서 일관성이없는 단점이 있지만 기본 테스트에서는 훨씬 넓은 범위의 문자를 포함하여 견고하고 의미있는 정렬 순서를 허용합니다.

에서 지적했듯이 Shog9귀하의 질문에 대한 답변은 다음과 같습니다.

return item1.attr.localeCompare(item2.attr);

더 읽을 거리 :

내가 믿는 “올바른”방향으로 나를 안내하는 Shog9의 훌륭한 답변 덕분에


답변

답변 (현대 ECMAScript에서)

list.sort((a, b) => (a.attr > b.attr) - (a.attr < b.attr))

또는

list.sort((a, b) => +(a.attr > b.attr) || -(a.attr < b.attr))

기술

부울 값을 숫자로 캐스팅하면 다음이 생성됩니다.

  • true -> 1
  • false -> 0

세 가지 가능한 패턴을 고려하십시오.

  • x는 y보다 큽니다 : (x > y) - (y < x)-> 1 - 0->1
  • x는 y와 같습니다 (x > y) - (y < x).-> 0 - 0->0
  • x는 y보다 작습니다 : (x > y) - (y < x)-> 0 - 1->-1

(대체)

  • x는 y보다 큽니다 : +(x > y) || -(x < y)-> 1 || 0->1
  • x는 y와 같습니다 +(x > y) || -(x < y).-> 0 || 0->0
  • x는 y보다 작습니다 : +(x > y) || -(x < y)-> 0 || -1->-1

따라서 이러한 논리는 일반적인 정렬 비교기 기능과 동일합니다.

if (x == y) {
    return 0;
}
return x > y ? 1 : -1;


답변

여기서는> 또는 <와 ==를 사용해야합니다. 따라서 해결책은 다음과 같습니다.

list.sort(function(item1, item2) {
    var val1 = item1.attr,
        val2 = item2.attr;
    if (val1 == val2) return 0;
    if (val1 > val2) return 1;
    if (val1 < val2) return -1;
});


답변

중첩 된 삼항 화살표 기능

(a,b) => (a < b ? -1 : a > b ? 1 : 0)


답변

문자열은 자바 스크립트에서 직접 비교할 수 있기 때문에이 작업을 수행합니다.

list.sort(function (a, b) {
    return a.attr > b.attr ? 1: -1;
})

정렬 함수에서 빼기는 알파벳이 아닌 (숫자) 정렬이 필요한 경우에만 사용되며 물론 문자열에서는 작동하지 않습니다.


답변

나는 이것에 대해 오랫동안 귀찮게 했으므로 마침내 이것을 연구하고 사물이 왜 그런지에 대한 긴 바람의 이유를 알려줍니다.

로부터 사양 :

Section 11.9.4   The Strict Equals Operator ( === )

The production EqualityExpression : EqualityExpression === RelationalExpression
is evaluated as follows:
- Let lref be the result of evaluating EqualityExpression.
- Let lval be GetValue(lref).
- Let rref be the result of evaluating RelationalExpression.
- Let rval be GetValue(rref).
- Return the result of performing the strict equality comparison
  rval === lval. (See 11.9.6)

이제 11.9.6으로갑니다

11.9.6   The Strict Equality Comparison Algorithm

The comparison x === y, where x and y are values, produces true or false.
Such a comparison is performed as follows:
- If Type(x) is different from Type(y), return false.
- If Type(x) is Undefined, return true.
- If Type(x) is Null, return true.
- If Type(x) is Number, then
...
- If Type(x) is String, then return true if x and y are exactly the
  same sequence of characters (same length and same characters in
  corresponding positions); otherwise, return false.

그게 다야. 인수가 정확히 동일한 문자열 (해당 위치의 길이와 문자가 동일) 인 경우 트리플 등호 연산자는 문자열에 적용됩니다.

따라서 ===다른 소스에서 온 문자열을 비교하려고 할 때 작동하지만 결국 코드의 인라인 문자열에 대한 일반적인 시나리오 인 동일한 값을 갖게됩니다. 예를 들어,이라는 변수가 있고 connection_state현재 다음 중 어느 상태인지 알고 자하는 경우 ['connecting', 'connected', 'disconnecting', 'disconnected']직접 사용할 수 있습니다.=== .

그러나 더 있습니다. 11.9.4 바로 위에 간단한 메모가 있습니다.

NOTE 4
  Comparison of Strings uses a simple equality test on sequences of code
  unit values. There is no attempt to use the more complex, semantically oriented
  definitions of character or string equality and collating order defined in the
  Unicode specification. Therefore Strings values that are canonically equal
  according to the Unicode standard could test as unequal. In effect this
  algorithm assumes that both Strings are already in normalized form.

흠. 지금 무엇? 외부 적으로 얻은 줄은 이상한 유니 코드 일 수 있으며 아마도 우리는 온화 ===하게 정의하지 않습니다. localeCompare구조에 온다 :

15.5.4.9   String.prototype.localeCompare (that)
    ...
    The actual return values are implementation-defined to permit implementers
    to encode additional information in the value, but the function is required
    to define a total ordering on all Strings and to return 0 when comparing
    Strings that are considered canonically equivalent by the Unicode standard. 

우리는 지금 집에 갈 수 있습니다.

tl; dr;

자바 스크립트에서 문자열을 비교하려면 localeCompare; 예를 들어 내부 프로그램 상수이기 때문에 문자열에 비 ASCII 구성 요소가없는 경우 ===에도 작동합니다.