Javascript - sort an array based on another array

Is it possible to sort and reorder an array that looks like this:

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

to match the location of this array:

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

Sorry, I don’t have tracking identifiers. I will need to move the items array so that it matches the Arr sort as close as possible.

Update:

Here is the result I'm looking for:

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

Any idea how this can be done?

+105
javascript
Nov 09 '12 at 8:29
source share
18 answers

Something like:

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

Here's a shorter code, but it destroys the sorting array:

 result = items.map(function(item) { var n = sorting.indexOf(item[1]); sorting[n] = ''; return [n, item] }).sort().map(function(j) { return j[1] }) 
+54
Nov 09 '12 at 8:57
source share

The answer is in one line.

 itemsArray.sort(function(a, b){ return sortingArr.indexOf(a) - sortingArr.indexOf(b); }); 
+117
May 19 '17 at 6:59 a.m.
source share

If you use the sort function of your own array, you can go to an arbitrary comparator, which will be used when sorting the array. The comparator should return a negative number if the first value is less than the second, zero if they are equal, and a positive number if the first value is greater.

So, if I understand the example you are giving correctly, you can do something like:

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

Case 1: original question (without libraries)

Lots of other answers that work. :)

Case 2: original question (Lodash.js or Underscore.js)

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

Case 3: Sort Array1 as if it were Array2

I assume most people came here to look for the PHP equivalent of array_multisort (I did), so I thought I would post this answer too. There are several options:

1. There exists an existing implementation of JS array_multisort () . Thanks to @Adnan for pointing this out in the comments. He is quite big.

2. Write your own. ( JSFiddle demo )

 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 or Underscore.js (both popular, smaller libraries that are performance-oriented) offer helper functions that allow you to do this:

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

... which will (1) group sortArray into pairs [index, value] , (2) sort them by value (you can also provide a callback here), (3) replace each of the pairs with an element from itemArray by index, from which arose a couple.

+25
Dec 05 '14 at 5:21
source share

maybe too late, but you can also use some modified version of the code below in ES6 style. This code is for arrays like:

 var arrayToBeSorted = [1,2,3,4,5]; var arrayWithReferenceOrder = [3,5,8,9]; 

Actual operation:

 arrayToBeSorted = arrayWithReferenceOrder.filter(v => arrayToBeSorted.includes(v)); 

Actual operation in ES5:

 arrayToBeSorted = arrayWithReferenceOrder.filter(function(v) { return arrayToBeSorted.includes(v); }); 

It should turn out arrayToBeSorted = [3,5]

Does not destroy the reference array.

+17
Dec 07 '16 at 22:19
source share

I would use an intermediate object ( itemsMap ) to avoid quadratic complexity:

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

See http://jsfiddle.net/eUskE/

+5
Nov 09 '12 at 9:08
source share
 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/

Resulting order: Bob, Jason, Henry, Thomas, Ann, Andrew

+3
Nov 09 '12 at 9:08
source share
 let a = ['A', 'B', 'C' ] let b = [3, 2, 1] let c = [1.0, 5.0, 2.0] // these array can be sorted by sorting order of b const zip = rows => rows[0].map((_, c) => rows.map(row => row[c])) const sortBy = (a, b, c) => { const zippedArray = zip([a, b, c]) const sortedZipped = zippedArray.sort((x, y) => x[1] - y[1]) return zip(sortedZipped) } sortBy(a, b, c) 
+2
Jun 12 '18 at 11:22
source share

I needed to do this for the JSON payload that I get from the API, but that was not in the order I wanted it.

The array that will be the reference array is the one you want to get in the second array:

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

I did this as objects, because in the end they will have other properties.

Created Array:

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

Used with a set of results from a database. I don't know how effective this is, but with the few columns that I used, it worked fine.

 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); }); 
+1
Feb 13 '17 at 22:56
source share

This is what I searched and did to sort an array of arrays based on another array:

This is ^ 3 and may not be best practice (ES6)

 function sortArray(arr, arr1){ return arr.map(item => { let a = []; for(let i=0; i< arr1.length; i++){ for (const el of item) { if(el == arr1[i]){ a.push(el); } } } return a; }); } const arr1 = ['fname', 'city', 'name']; const arr = [['fname', 'city', 'name'], ['fname', 'city', 'name', 'name', 'city','fname']]; console.log(sortArray(arr,arr1)); 
It may help someone
+1
25 sept. '18 at 6:13
source share
 let sortedOrder = [ 'b', 'c', 'b', 'b' ] let itemsArray = [ ['Anne', 'a'], ['Bob', 'b'], ['Henry', 'b'], ['Andrew', 'd'], ['Jason', 'c'], ['Thomas', 'b'] ] a.itemsArray(function (a, b) { let A = a[1] let B = b[1] if(A != undefined) A = A.toLowerCase() if(B != undefined) B = B.toLowerCase() let indA = sortedOrder.indexOf(A) let indB = sortedOrder.indexOf(B) if (indA == -1 ) indA = sortedOrder.length-1 if( indB == -1) indB = sortedOrder.length-1 if (indA < indB ) { return -1; } else if (indA > indB) { return 1; } return 0; }) 

This solution will add objects at the end if the sort key is not in the referenced array.

+1
Mar 11 '19 at 16:07
source share

this should work:

 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; 
0
Nov 09 '12 at 9:05
source share

To get a new ordered array, you can take a Map and collect all the elements with the required key in the array and display the required ordered keys by taking the sifted element of the desired group.

 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); 
0
Oct 31 '18 at 13:21
source share

You can try this method.

 const sortListByRanking = (rankingList, listToSort) => { let result = [] for (let id of rankingList) { for (let item of listToSort) { if (item && item[1] === id) { result.push(item) } } } return result } 
0
Feb 01 '19 at 7:50
source share

Why not something like

 //array1: array of elements to be sorted //array2: array with the indexes array1 = array2.map((object, i) => array1[object]); 

Map feature may not be available in all versions of Javascript

0
Feb 27 '19 at 19:49
source share

Use the $ .inArray () method from jQuery. Then you could do something like this

 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]); } 
-one
Nov 09 '12 at 8:36
source share

Use the intersection of two arrays.

Example:

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

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

if 'z and' s' are out of range of the first array, add it to the end of the result

-one
Sep 28 '16 at 18:24
source share

You can do something like this:

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

Here you can check it out .

Note: this assumes that the arrays you are passing are equivalent in size, you need to add extra checks if this might not be the case.

send link

contact

-2
Nov 09 '12 at 8:37
source share



All Articles