Javascript : 자연스러운 영숫자 문자열
숫자와 텍스트, 그리고 이들의 조합으로 구성된 배열을 가장 쉽게 정렬할 수 있는 방법을 찾고 있습니다.
예.
'123asd'
'19asd'
'12345asd'
'asd123'
'asd12'
로 바뀌다
'19asd'
'123asd'
'12345asd'
'asd12'
'asd123'
이것은 여기서 질문한 다른 질문에 대한 해결책과 조합하여 사용합니다.
정렬 기능 자체가 작동하기 때문에 19asd가 123asd보다 작다고 할 수 있는 기능이 필요합니다.
JavaScript로 쓰고 있습니다.
편집 : adormitu가 지적한 바와 같이, 제가 찾고 있는 것은 자연스러운 정렬 기능입니다.
이것은 현재 local Compare를 사용하는 최신 브라우저에서 가능합니다.통과함으로써numeric: true
스마트하게 숫자를 인식할 수 있습니다.대소문자를 구분하지 않고sensitivity: 'base'
. Chrome, Firefox 및 IE11에서 테스트 완료.
여기 예가 있어요.다시 돌아오다1
10은 2 뒤에 오는 것을 의미합니다.
'10'.localeCompare('2', undefined, {numeric: true, sensitivity: 'base'})
다수의 문자열을 정렬할 때의 퍼포먼스를 위해 기사에는 다음과 같이 기재되어 있습니다.
대규모 배열 정렬 등 다수의 문자열을 비교할 때는 Intl을 작성하는 것이 좋습니다.오브젝트를 대조하여 비교 속성에 의해 제공되는 함수를 사용합니다.Docs 링크
var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
var myArray = ['1_Document', '11_Document', '2_Document'];
console.log(myArray.sort(collator.compare));
개체 배열이 있는 경우 다음과 같이 수행할 수 있습니다.
myArrayObjects = myArrayObjects.sort(function(a, b) {
return a.name.localeCompare(b.name, undefined, {
numeric: true,
sensitivity: 'base'
});
});
var myArrayObjects = [{
"id": 1,
"name": "1 example"
},
{
"id": 2,
"name": "100 example"
},
{
"id": 3,
"name": "12 example"
},
{
"id": 4,
"name": "5 example"
},
]
myArrayObjects = myArrayObjects.sort(function(a, b) {
return a.name.localeCompare(b.name, undefined, {
numeric: true,
sensitivity: 'base'
});
});
console.log(myArrayObjects);
값을 비교하려면 비교 방법을 사용할 수 있습니다.
function naturalSorter(as, bs){
var a, b, a1, b1, i= 0, n, L,
rx=/(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.\D+)|(\.$)/g;
if(as=== bs) return 0;
a= as.toLowerCase().match(rx);
b= bs.toLowerCase().match(rx);
L= a.length;
while(i<L){
if(!b[i]) return 1;
a1= a[i],
b1= b[i++];
if(a1!== b1){
n= a1-b1;
if(!isNaN(n)) return n;
return a1>b1? 1:-1;
}
}
return b[i]? -1:0;
}
그러나 배열 정렬 속도를 높이려면 정렬하기 전에 배열을 조정해야 합니다. 따라서 정렬을 통과하는 모든 단계가 아니라 소문자 변환과 정규 표현을 한 번만 수행하면 됩니다.
function naturalSort(ar, index){
var L= ar.length, i, who, next,
isi= typeof index== 'number',
rx= /(\.\d+)|(\d+(\.\d+)?)|([^\d.]+)|(\.(\D+|$))/g;
function nSort(aa, bb){
var a= aa[0], b= bb[0], a1, b1, i= 0, n, L= a.length;
while(i<L){
if(!b[i]) return 1;
a1= a[i];
b1= b[i++];
if(a1!== b1){
n= a1-b1;
if(!isNaN(n)) return n;
return a1>b1? 1: -1;
}
}
return b[i]!= undefined? -1: 0;
}
for(i= 0; i<L; i++){
who= ar[i];
next= isi? ar[i][index] || '': who;
ar[i]= [String(next).toLowerCase().match(rx), who];
}
ar.sort(nSort);
for(i= 0; i<L; i++){
ar[i]= ar[i][1];
}
}
숫자 제로 패딩 기능을 상상해 보십시오.n => n.padStart(8, "0")
어떤 숫자든 가져와서 패드를 채우는 거죠
- '19' -> '00000019'
- "123" -> "00000123"
이 함수는 다음 항목을 정렬하는 데 사용할 수 있습니다."19"
스트링 앞에 표시되도록 합니다."123"
스트링
정규식을 추가합시다./\d+/g
자연팽창함수 생성str => str.replace(/\d+/g, n => n.padStart(8, "0"))
문자열에서 숫자 섹션만 찾아 패드를 채웁니다.
- "1920" -> "00000019"
- "123g" -> "00000123g"
이제 이 자연 확장 함수를 사용하여 자연 순서 정렬을 구현할 수 있습니다.
const list = [
"123asd",
"19asd",
"12345asd",
"asd123",
"asd12"
];
const ne = str => str.replace(/\d+/g, n => n.padStart(8, "0"));
const nc = (a,b) => ne(a).localeCompare(ne(b));
console.log(list.map(ne).sort()); // intermediate values
console.log(list.sort(nc)); // result
중간 결과는 다음과 같습니다.list.map(ne).sort()
어떤 것을 보여주다ne
자연팽창함수가 그러합니다.문자열의 숫자 부분에만 숫자 제로 패딩을 구현하고 알파벳 구성 요소는 변경하지 않습니다.
[
"00000019asd",
"00000123asd",
"00012345asd",
"asd00000012",
"asd00000123"
]
솔루션의 최종 버전은 자연스러운 순서 비교기를 구현합니다.nc
(a,b) => ne(a).localeCompare(ne(b))
에사니다다 and에서 사용합니다.list.sort(nc)
올바르게 순서를 매길 수 있도록 합니다.
[
"19asd",
"123asd",
"12345asd",
"asd12",
"asd123"
]
2019년 현재 이를 처리할 수 있는 가장 완전한 기능을 갖춘 라이브러리는 내추럴 오더바이인 것 같습니다.
import { orderBy } from 'natural-orderby'
const unordered = [
'123asd',
'19asd',
'12345asd',
'asd123',
'asd12'
]
const ordered = orderBy(unordered)
// [ '19asd',
// '123asd',
// '12345asd',
// 'asd12',
// 'asd123' ]
문자열 배열을 필요로 할 뿐만 아니라 객체 배열에 포함된 특정 키의 값을 기준으로 정렬할 수도 있습니다.또한 통화, 날짜, 통화 및 기타 여러 문자열도 자동으로 식별하고 정렬할 수 있습니다.
놀랍게도 gzip 했을 때도 1.6kB밖에 되지 않습니다.
위의 @Adrien Be의 답변을 바탕으로 Brian Huisman & David Koelle이 작성한 코드를 사용하여 오브젝트 배열의 수정된 프로토타입 정렬을 다음에 나타냅니다.
//Usage: unsortedArrayOfObjects.alphaNumObjectSort("name");
//Test Case: var unsortedArrayOfObjects = [{name: "a1"}, {name: "a2"}, {name: "a3"}, {name: "a10"}, {name: "a5"}, {name: "a13"}, {name: "a20"}, {name: "a8"}, {name: "8b7uaf5q11"}];
//Sorted: [{name: "8b7uaf5q11"}, {name: "a1"}, {name: "a2"}, {name: "a3"}, {name: "a5"}, {name: "a8"}, {name: "a10"}, {name: "a13"}, {name: "a20"}]
// **Sorts in place**
Array.prototype.alphaNumObjectSort = function(attribute, caseInsensitive) {
for (var z = 0, t; t = this[z]; z++) {
this[z].sortArray = new Array();
var x = 0, y = -1, n = 0, i, j;
while (i = (j = t[attribute].charAt(x++)).charCodeAt(0)) {
var m = (i == 46 || (i >=48 && i <= 57));
if (m !== n) {
this[z].sortArray[++y] = "";
n = m;
}
this[z].sortArray[y] += j;
}
}
this.sort(function(a, b) {
for (var x = 0, aa, bb; (aa = a.sortArray[x]) && (bb = b.sortArray[x]); x++) {
if (caseInsensitive) {
aa = aa.toLowerCase();
bb = bb.toLowerCase();
}
if (aa !== bb) {
var c = Number(aa), d = Number(bb);
if (c == aa && d == bb) {
return c - d;
} else {
return (aa > bb) ? 1 : -1;
}
}
}
return a.sortArray.length - b.sortArray.length;
});
for (var z = 0; z < this.length; z++) {
// Here we're deleting the unused "sortArray" instead of joining the string parts
delete this[z]["sortArray"];
}
}
언급URL : https://stackoverflow.com/questions/2802341/javascript-natural-sort-of-alphanumerical-strings
'itsource' 카테고리의 다른 글
다차원 배열의 모든 하위 배열 요소를 다시 인덱싱하려면 어떻게 해야 합니까? (0) | 2022.09.26 |
---|---|
사전의 최소값에 해당하는 키를 가져옵니다. (0) | 2022.09.26 |
실행 중인 Python 스크립트의 경로를 얻으려면 어떻게 해야 합니까? (0) | 2022.09.25 |
C99는 얼마나 일반적으로 지원됩니까? (0) | 2022.09.25 |
해시 '#'이 없는 AngularJS 라우팅 (0) | 2022.09.25 |