262

次のような配列を並べ替えて再配置することは可能ですか。

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'],
]

これを行う方法はありますか?

4

25 に答える 25

94

何かのようなもの:

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] })
于 2012-11-09T08:57:09.050 に答える
47

ネイティブの配列ソート関数を使用する場合は、配列をソートするときに使用するカスタム コンパレータを渡すことができます。コンパレータは、最初の値が 2 番目の値より小さい場合は負の数を返し、等しい場合はゼロを返し、最初の値が大きい場合は正の数を返します。

したがって、あなたが正しく示している例を理解できれば、次のようなことができます。

function sortFunc(a, b) {
  var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
  return sortingArr.indexOf(a[1]) - sortingArr.indexOf(b[1]);
}

itemsArray.sort(sortFunc);
于 2012-11-09T08:46:59.167 に答える
31

ケース 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 のアイテムに置き換えます。から生まれたペア。

于 2014-12-05T05:21:33.067 に答える
23

これはおそらく手遅れですが、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]

参照配列を破棄しません。

于 2016-12-07T22:19:48.193 に答える
8

中間オブジェクト ( 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/を参照

于 2012-11-09T09:08:46.877 に答える
6
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/

結果の順序: ボブ、ジェイソン、ヘンリー、トーマス、アン、アンドリュー

于 2012-11-09T09:08:09.603 に答える
3

新しい順序付けられた配列を取得するMapには、配列内の必要なキーを持つすべてのアイテムを取得して収集し、必要なグループのふるいにかけられた要素を取得して、必要な順序付けされたキーをマップできます。

var itemsArray = [['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b']],
    sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ],
    map = itemsArray.reduce((m, a) => m.set(a[1], (m.get(a[1]) || []).concat([a])), new Map),
    result = sortingArr.map(k => (map.get(k) || []).shift());

console.log(result);

于 2018-10-31T13:21:56.167 に答える
-1

2 つの配列の交点を使用します。

元:

var sortArray = ['a', 'b', 'c',  'd', 'e'];

var arrayToBeSort = ['z', 's', 'b',  'e', 'a'];

_.intersection(sortArray, arrayToBeSort) 

=> ['a', 'b', 'e']

「z」と「s」が最初の配列の範囲外の場合、結果の最後に追加します

于 2016-09-28T18:24:15.867 に答える
-1

jQuery の $.inArray() メソッドを使用します。次に、このようなことができます

var sortingArr = [ 'b', 'c', 'b', 'b', 'c', 'd' ];
var newSortedArray = new Array();

for(var i=sortingArr.length; i--;) {
 var foundIn = $.inArray(sortingArr[i], itemsArray);
 newSortedArray.push(itemsArray[foundIn]);
}
于 2012-11-09T08:36:23.867 に答える
-5

次のようなことができます。

function getSorted(itemsArray , sortingArr ) {
  var result = [];
  for(var i=0; i<arr.length; i++) {
    result[i] = arr[sortArr[i]];
  }
  return result;
}

ここでテストできます

注:これは、渡す配列のサイズが等しいことを前提としています。そうでない場合は、追加のチェックを追加する必要があります。

リンクを参照

参照

于 2012-11-09T08:37:28.673 に答える