[javascript] 자바 스크립트-다른 배열을 기준으로 배열 정렬

다음과 같은 배열을 정렬하고 재 배열 할 수 있습니까?

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;
}

http://jsfiddle.net/eUskE/ 참조


답변

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;
        }
    }
}

http://jsfiddle.net/s7b2P/

결과 주문 : Bob, Jason, Henry, Thomas, Anne, Andrew