Sort an array in the same order of another array
Asked Answered
D

5

17

I have a few arrays of 50+ names like this.

["dan", "ryan", "bob", "steven", "corbin"]
["bob", "dan", "steven", "corbin"]

I have another array that has the correct order. Note that the second array above does not include all of the names, but I still want it to follow the order of the following:

["ryan", "corbin", "dan", "steven", "bob"]

There is no logical order to it, they are just in this order. What makes sense to me is to compare each array against the correctly ordered one. I think I saw some people doing this with PHP, but I was not able to find a JavaScript solution. Does anyone have any idea how to do this? I've been trying for a few hours and I'm stumped.

Dieter answered 7/2, 2015 at 1:25 Comment(1)
Is there a specific reason reason you want them in that order? If you just want them in the same order you can just use .sort() on both of the arrays.Electrochemistry
V
41

Use indexOf() to get the position of each element in the reference array, and use that in your comparison function.

var reference_array = ["ryan", "corbin", "dan", "steven", "bob"];
var array = ["bob", "dan", "steven", "corbin"];
array.sort(function(a, b) {
  return reference_array.indexOf(a) - reference_array.indexOf(b);
});
console.log(array); // ["corbin", "dan", "steven", "bob"]

Searching the reference array every time will be inefficient for large arrays. If this is a problem, you can convert it into an object that maps names to positions:

var reference_array = ["ryan", "corbin", "dan", "steven", "bob"];
reference_object = {};
for (var i = 0; i < reference_array.length; i++) {
    reference_object[reference_array[i]] = i;
}
var array = ["bob", "dan", "steven", "corbin"];
array.sort(function(a, b) {
  return reference_object[a] - reference_object[b];
});
console.log(array);
Virgilio answered 7/2, 2015 at 1:35 Comment(2)
This works & answers the question I asked. I asked the question without saying my original array was actually an object. To fix this, I was able to get the keys from the object using _.keys, then I was able to sort them using your method reference_array.indexOf(a) - reference_array.indexOf(b); I asked a 2nd question with my exact code (#28395977), but in the end I had to figure out the conversion of object to array. I used this answer and the one over there to finally solve my sorting problem.Dieter
You should remember to tag your questions with underscorejs if you're interested in solutions using that library.Virgilio
B
1

You can realize some sorter by patter factory function. Then create sorter using your pattern and apply it to your arrays:

function sorterByPattern(pattern) {
    var hash = {};
    pattern.forEach(function(name, index) { hash[name] = index });

    return function(n1, n2) {
        if (!(n1 in hash)) return 1;  // checks if name is not in the pattern
        if (!(n2 in hash)) return -1; // if true - place that names to the end
        return hash[n1] - hash[n2];
    }
}

var sorter = sorterByPattern(["ryan", "corbin", "dan", "steven", "bob"]);

var arrays = [
    ["dan", "ryan", "bob", "steven", "corbin"],
    ["bob", "dan", "steven", "corbin"]
    /* ... */
];

arrays.forEach(function(array) { array.sort(sorter) });
Basham answered 7/2, 2015 at 1:48 Comment(0)
V
1

I had the same issue now and I tried a bit different approach. It does not sort the arrays but filtering the order-list according to sorting-lists so it has got some limitations but for my needs it's event better because it gets rid of incorrect values from sorted list:

  • if sorting-list has got doubled value, it will occure just once in sorted list
  • if sorting-list has got item which is not included in order-list, it will not appear in sorted list

function sortOrder(getOrder,getArr){
  return getOrder.filter(function(order){
    return getArr.some(function(list){
      return order === list;
    });
  });
}

//arrays
var order = ["ryan", "corbin", "dan", "steven", "bob"];
var arA = ["dan", "ryan", "bob", "steven", "corbin"];
var arB = ["bob", "dan", "steven", "corbin"];
var arC = ["bob","ryan"];
var arD = ["bob","bob","corbin"]; //remove repetition
var arE = ["unrecognizedItem","corbin","steven","ryan"]; //remove the item not included in order array

//print results
document.body.innerHTML = sortOrder(order,arA)+'<br/>';
document.body.innerHTML += sortOrder(order,arB)+'<br/>';
document.body.innerHTML += sortOrder(order,arC)+'<br/>';
document.body.innerHTML += sortOrder(order,arD)+'<br/>';
document.body.innerHTML += sortOrder(order,arE)+'<br/>';
Viscounty answered 22/12, 2016 at 18:49 Comment(0)
B
0

If you need to place values of your array in the recurring order, meaning:
Input: [1, 2, 4, 4, 3, 3, 2, 1]
Output: [1, 2, 3, 4, 1, 2, 3, 4]

Then you can use 2 functions below. The first one uses the second one.
For the first function you will need to provide 2 arguments:
1st argument: your array of items that should be ordered (Input from above)
2nd argument: array of the correct order ([1, 2, 3, 4] for the example above)

function sortByOrder (array, order) {

    const arrayOfArrays = order.map(v => {

        return [...Array(howMany(v, array))].map(undef => v);
    });

    const tempArray = [];

    arrayOfArrays.forEach((subArr, i) => {

        let index = order.indexOf(order[i]);

        subArr.forEach(duplicate => {

            tempArray[index] = duplicate;

            index += order.length;
        });
    });

    return tempArray.filter(v => v);
}

function howMany(value, array) {

        const regExp = new RegExp(value, 'g');

        return (array.join(' ').match(regExp) || []).length;
}
Beguile answered 15/11, 2017 at 10:54 Comment(0)
I
0
var a = ["Senior", "Junior", "Intern", "Office Assistant"];
var b = ["Junior", "Cleaner", "Senior", "Intern", "Office Assistant"];

var res = [];

for (var i = 0; i < a.length; i++) {
  for (var j = 0; j < b.length; j++) {
    if (a[i] == b[j]) {
      res.push(b[j]);
      b.splice(b.indexOf(b[j]), 1)
      break;
    }
  }
}

console.log(res.concat(b)); // [ 'Senior', 'Junior', 'Intern', 'Office Assistant', 'Cleaner' ]
Isolationist answered 21/7, 2023 at 15:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.