다음과 같은 배열을 정렬하고 재 배열 할 수 있습니까?
itemsArray = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
이 배열의 배열과 일치합니다.
sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ]
유감스럽게도 추적 할 ID가 없습니다. sortingArr과 최대한 일치하도록 items-array의 우선 순위를 지정해야합니다.
최신 정보:
내가 찾고있는 출력은 다음과 같습니다.
itemsArray = [
['Bob', 'b'],
['Jason', 'c'],
['Henry', 'b'],
['Thomas', 'b']
['Anne', 'a'],
['Andrew', 'd'],
]
이것이 어떻게 이루어질 수 있는지 아십니까?
답변
다음과 같은 것 :
items = [
['Anne', 'a'],
['Bob', 'b'],
['Henry', 'b'],
['Andrew', 'd'],
['Jason', 'c'],
['Thomas', 'b']
]
sorting = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
result = []
sorting.forEach(function(key) {
var found = false;
items = items.filter(function(item) {
if(!found && item[1] == key) {
result.push(item);
found = true;
return false;
} else
return true;
})
})
result.forEach(function(item) {
document.writeln(item[0]) /// Bob Jason Henry Thomas Andrew
})
더 짧은 코드가 있지만 sorting
배열을 파괴합니다 .
result = items.map(function(item) {
var n = sorting.indexOf(item[1]);
sorting[n] = '';
return [n, item]
}).sort().map(function(j) { return j[1] })
답변
한 줄 답변.
itemsArray.sort(function(a, b){
return sortingArr.indexOf(a) - sortingArr.indexOf(b);
});
답변
기본 배열 정렬 기능을 사용하는 경우 배열을 정렬 할 때 사용할 사용자 정의 비교기를 전달할 수 있습니다. 비교기는 첫 번째 값이 두 번째 값보다 작 으면 음수를 반환하고, 같으면 0을, 첫 번째 값이 큰 경우 양수를 반환해야합니다.
따라서 올바르게 제공 한 예를 이해하면 다음과 같이 할 수 있습니다.
function sortFunc(a, b) {
var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}
itemsArray.sort(sortFunc);
답변
사례 1 : 원래 질문 (라이브러리 없음)
작동하는 다른 답변이 많이 있습니다. 🙂
사례 2 : 원래 질문 (Lodash.js 또는 Underscore.js)
var groups = _.groupBy(itemArray, 1);
var result = _.map(sortArray, function (i) { return groups[i].shift(); });
사례 3 : Array1을 Array2 인 것처럼 정렬
나는 대부분의 사람들이 PHP의 array_multisort (내가 한)와 동등한 것을 찾고 여기에 왔기 때문에 그 대답을 게시 할 것이라고 생각했습니다. 몇 가지 옵션이 있습니다.
1. array_multisort () 의 기존 JS 구현이 있습니다. 의견에서 지적한 @Adnan에게 감사합니다. 그래도 꽤 큽니다.
2. 직접 작성하십시오. ( JSFiddle 데모 )
function refSort (targetData, refData) {
// Create an array of indices [0, 1, 2, ...N].
var indices = Object.keys(refData);
// Sort array of indices according to the reference data.
indices.sort(function(indexA, indexB) {
if (refData[indexA] < refData[indexB]) {
return -1;
} else if (refData[indexA] > refData[indexB]) {
return 1;
}
return 0;
});
// Map array of indices to corresponding values of the target array.
return indices.map(function(index) {
return targetData[index];
});
}
3. Lodash.js 또는 Underscore.js (성능에 중점을 둔 인기있는 작은 라이브러리)는 다음을 수행 할 수있는 도우미 기능을 제공합니다.
var result = _.chain(sortArray)
.pairs()
.sortBy(1)
.map(function (i) { return itemArray[i[0]]; })
.value();
… (1) sortArray를 [index, value]
쌍 으로 그룹화하고 (2) 값으로 정렬합니다 (여기서 콜백을 제공 할 수도 있음) (3) 각 쌍을 인덱스의 itemArray 항목으로 바꿉니다. 쌍에서 유래.
답변
이것은 아마도 너무 늦었지만 ES6 스타일에서 아래 코드의 수정 된 버전을 사용할 수도 있습니다. 이 코드는 다음과 같은 배열을위한 것입니다.
var arrayToBeSorted = [1,2,3,4,5];
var arrayWithReferenceOrder = [3,5,8,9];
실제 작업 :
arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v));
ES5의 실제 작동 :
arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) {
return arrayToBeSorted.includes(v);
});
결과 arrayToBeSorted = [3,5]
참조 배열을 파괴하지 않습니다.
답변
중간 객체 ( itemsMap
)를 사용하여 이차 복잡성을 피합니다.
function createItemsMap(itemsArray) { // {"a": ["Anne"], "b": ["Bob", "Henry"], …}
var itemsMap = {};
for (var i = 0, item; (item = itemsArray[i]); ++i) {
(itemsMap[item[1]] || (itemsMap[item[1]] = [])).push(item[0]);
}
return itemsMap;
}
function sortByKeys(itemsArray, sortingArr) {
var itemsMap = createItemsMap(itemsArray), result = [];
for (var i = 0; i < sortingArr.length; ++i) {
var key = sortingArr[i];
result.push([itemsMap[key].shift(), key]);
}
return result;
}
답변
var sortedArray = [];
for(var i=0; i < sortingArr.length; i++) {
var found = false;
for(var j=0; j < itemsArray.length && !found; j++) {
if(itemsArray[j][1] == sortingArr[i]) {
sortedArray.push(itemsArray[j]);
itemsArray.splice(j,1);
found = true;
}
}
}
결과 주문 : Bob, Jason, Henry, Thomas, Anne, Andrew