Javascript – 基于另一个数组sorting数组

是否有可能sorting和重新排列如下所示的数组:

itemsArray = [ ['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b'] ] 

来匹配这个数组的排列:

 sortingArr = [ 'b', 'c', 'b', 'b', 'a', 'd' ] 

不幸的是,我没有任何ID来跟踪。 我需要优先的items-array尽可能地与sortArr匹配。

更新:

这是我正在寻找的输出:

 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] }) 

案例1:原始问题(无图书馆)

许多其他的答案,工作。 🙂

案例2:原始问题(Lodash.js或Underscore.js)

 var groups = _.groupBy(itemArray, 1); var result = _.map(sortArray, function (i) { return groups[i].shift(); }); 

情况3:将Array1sorting为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 (这两个stream行的小型库专注于性能)提供帮助函数,允许您这样做:

  var result = _.chain(sortArray) .pairs() .sortBy(1) .map(function (i) { return itemArray[i[0]]; }) .value(); 

(1)将sortArray分组到[index, value]对中,(2)按值sorting(也可以在这里提供callback),(3)用itemArray在该对来源的索引处。

如果使用本地数组sorting函数,则可以传入一个自定义比较器来sorting数组。 如果第一个值小于第二个值,则比较器应该返回一个负数,如果它们相等,则返回零;如果第一个值较大,则返回正数。

所以如果我理解你正确的给出的例子,你可以做一些事情:

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

这可能太晚了,但是,你也可以在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]

不要销毁参考数组。

一线答案。

 itemsArray.sort(function(a, b){ return sortingArr.indexOf(a) > sortingArr.indexOf(b) ? 1 : -1; }); 

我会使用中间对象( 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

我必须这样做,我从API接收的JSON有效载荷,但它不是我想要的顺序。

数组作为参考数组,你想第二个数组sorting:

 var columns = [ {last_name: "last_name"}, {first_name: "first_name"}, {book_description: "book_description"}, {book_id: "book_id"}, {book_number: "book_number"}, {due_date: "due_date"}, {loaned_out: "loaned_out"} ]; 

我做这些作为对象,因为这些将最终有其他属性。

创build数组:

  var referenceArray= []; for (var key in columns) { for (var j in columns[key]){ referenceArray.push(j); } } 

与数据库的结果集一起使用。 我不知道它是如何有效的,但是我使用的列数很less,它工作得很好。

 result.forEach((element, index, array) => { var tr = document.createElement('tr'); for (var i = 0; i < referenceArray.length - 1; i++) { var td = document.createElement('td'); td.innerHTML = element[referenceArray[i]]; tr.appendChild(td); } tableBody.appendChild(tr); }); 

使用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]); } 

你可以做这样的事情:

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

你可以在这里testing一下 。

注意:这里假设你传入的数组大小是相等的,如果情况不是这样,你需要添加一些额外的检查。

参考链接

参考

这应该工作:

 var i,search, itemsArraySorted = []; while(sortingArr.length) { search = sortingArr.shift(); for(i = 0; i<itemsArray.length; i++) { if(itemsArray[i][1] == search) { itemsArraySorted.push(itemsArray[i]); break; } } } itemsArray = itemsArraySorted; 

使用两个数组的交集。

例如:

 var sortArray = ['a', 'b', 'c', 'd', 'e']; var arrayToBeSort = ['z', 's', 'b', 'e', 'a']; _.intersection(sortArray, arrayToBeSort) 

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

如果'z'和's'超出第一个数组的范围,则将其附加在结果的末尾