Home > Back-end >  How to sort a 2D array by the first column using values of another array?
How to sort a 2D array by the first column using values of another array?

Time:09-17

I have a 2D array:

var array1 = [
["Jasper", "Diesel", "Grid", 2.7],
["Delta", "Solar", "Grid", 10],
["Alpha", "Wind", "Grid", 20]
]

I want to sort array1 by the first column using:

var sortingArray = ["Alpha","Jasper","Delta]

So it should look like this:

var sortedArray = [
["Alpha", "Wind", "Grid", 20],    
["Jasper", "Diesel", "Grid", 2.7],
["Delta", "Solar", "Grid", 10]
]

I've already tried using the below sort function but it doesn't change the array at all. Do I not need to specify which position I want to sort?

array1.sort(function (a, b) {  
  return sortingArray.indexOf(a) - sortingArray.indexOf(b);
})

UPDATE: Since posting I have solved the issue. As I suspected, I did need to provide which position I wanted to sort. The solution is:

array1.sort(function (a, b) {  
  return sortingArray.indexOf(a[0) - sortingArray.indexOf(b[0]);
})

CodePudding user response:

a and b are arrays, the first elements are strings. You can compare strings using localeCompare string method:

array1.sort((a, b) => a[0].localeCompare(b[0]))

CodePudding user response:

array1.sort(function (a, b) {  
   return sortingArray.indexOf(a[0) - sortingArray.indexOf(b[0]);
})

CodePudding user response:

You could reduce the sorting array into a Map for quick look-up.

const array1 = [
  ["Jasper", "Diesel", "Grid", 2.7],
  ["Delta", "Solar", "Grid", 10],
  ["Alpha", "Wind", "Grid", 20]
]

const sortingArray = ["Alpha", "Jasper", "Delta"];

/**
 * Sorts the data by a list of values.
 * @param {Object[]|Array[]} data - an array of objects or arrays
 * @param {String|Number} fieldOrIndex - a field name or index
 * @param {String[]} order - the sorting order of the values
 * @return {Object[]|Array[]} sorted data
 */
const sortWith = (data, fieldOrIndex, order) => {
  const orderMap = order.reduce((acc, token, index) =>
    acc.set(token, index), new Map);
  return data.sort((a, b) =>
    orderMap.get(a[fieldOrIndex]) - orderMap.get(b[fieldOrIndex]));
};

const sorted = sortWith(array1, 0, sortingArray);

console.log(sorted);
.as-console-wrapper { top: 0; max-height: 100% !important; }

If your list or items is small, you can skip the map and just grab the indices.

const array1 = [
  ["Jasper", "Diesel", "Grid", 2.7],
  ["Delta", "Solar", "Grid", 10],
  ["Alpha", "Wind", "Grid", 20]
]

const sortingArray = ["Alpha", "Jasper", "Delta"];

/**
 * Sorts the data by a list of values.
 * @param {Object[]|Array[]} data - an array of objects or arrays
 * @param {String|Number} fieldOrIndex - a field name or index
 * @param {String[]} order - the sorting order of the values
 * @return {Object[]|Array[]} sorted data
 */
const sortWith = (data, fieldOrIndex, order) =>
  data.sort((a, b) =>
    order.indexOf(a[fieldOrIndex]) - order.indexOf(b[fieldOrIndex]));

const sorted = sortWith(array1, 0, sortingArray);

console.log(sorted);
.as-console-wrapper { top: 0; max-height: 100% !important; }

  • Related