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; }
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
我必须这样做,我从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'超出第一个数组的范围,则将其附加在结果的末尾