Sort by two values prioritizing on one of them

JavascriptSorting

Javascript Problem Overview


How would I sort this data by count and year values in ascending order prioritizing on the count value?

//sort this
var data = [
	{ count: '12', year: '1956' },
	{ count: '1', year: '1971' },
	{ count: '33', year: '1989' },
	{ count: '33', year: '1988' }
];
//to get this
var data = [
	{ count: '1', year: '1971' },
	{ count: '12', year: '1956' },
	{ count: '33', year: '1988' },
	{ count: '33', year: '1989' },
];

Javascript Solutions


Solution 1 - Javascript

(See the jsfiddle)

var data = [
    { count: '12', year: '1956' },
    { count: '1', year: '1971' },
    { count: '33', year: '1989' },
    { count: '33', year: '1988' }
];

console.log(data.sort(function (x, y) {
    var n = x.count - y.count;
    if (n !== 0) {
        return n;
    }

    return x.year - y.year;
}));

Solution 2 - Javascript

A simple solution is:

data.sort(function (a, b) {
  return a.count - b.count || a.year - b.year;
});

This works because if count is different, then the sort is based on that. If count is the same, the first expression returns 0 which converts to false and the result of the second expression is used (i.e. the sort is based on year).

Solution 3 - Javascript

You can use JavaScript's .sort() array method (try it out):

data.sort(function(a, b) {
    // Sort by count
    var dCount = a.count - b.count;
    if(dCount) return dCount;

    // If there is a tie, sort by year
    var dYear = a.year - b.year;
    return dYear;
});

Note: This changes the original array. If you need to make a copy first, you can do so:

var dataCopy = data.slice(0);

Solution 4 - Javascript

Based on great @RobG solution, this is a generic function to sort by multiple different properties, using a JS2015 tricky on map + find:

let sortBy = (p, a) => a.sort((i, j) => p.map(v => i[v] - j[v]).find(r => r))

sortBy(['count', 'year'], data)

Also, if you prefer, a traditional JS version (use with caution due to find compatibility in old browsers):

var sortBy = function (properties, targetArray) {
  targetArray.sort(function (i, j) {
    return properties.map(function (prop) {
      return i[prop] - j[prop];
    }).find(function (result) {
      return result;
    });
  });
};

Solution 5 - Javascript

you have to work out this problem like this way

var customSort = function(name, type){
     return function(o, p){
         var a, b;
         if(o && p && typeof o === 'object' && typeof p === 'object'){
            a = o[name];
            b = p[name];
           if(a === b){
              return typeof type === 'function' ? type(o, p) : o;
           }
          
           if(typeof a=== typeof b){
              return a < b ? -1 : 1;
            }
          return typeof a < typeof b ? -1 : 1;
        }
     };

};

e.g : data.sort(customSort('year', customSort('count')));

Solution 6 - Javascript

user this where 'count'-> first priority and 'year'-> second priority

data.sort(function(a,b){
  return a['count']<b['count']?-1:(a['count']>b['count']?1:(a['year']<b['year']?-1:1));
});

Solution 7 - Javascript

If you are looking to sort strings in alphabetical order rather than numbers, here's a sample problem and its solution.

Example Problem: Array of arrays (finalArray) with first entry a folder path and second entry the file name; sort so that array is arranged by folder first, and within identical folders, by file name.

E.g. after sorting you expect:

[['folder1', 'abc.jpg'], 
 ['folder1', 'xyz.jpg'],
 ['folder2', 'def.jpg'],
 ['folder2', 'pqr.jpg']]

Refer to Array.prototype.sort() - compareFunction

finalArray.sort((x: any, y: any): number => {
  const folder1: string = x[0].toLowerCase();
  const folder2: string = y[0].toLowerCase();
  const file1: string = x[1].toLowerCase();
  const file2: string = y[1].toLowerCase();

  if (folder1 > folder2) {
    return 1;
  } else if (folder1 === folder2 && file1 > file2) {
    return 1;
  } else if (folder1 === folder2 && file1 === file2) {
    return 0;
  } else if (folder1 === folder2 && file1 < file2) {
    return -1;
  } else if (folder1 < folder2) {
    return -1;
  }
});

Keep in mind, "Z" comes before "a" (capitals first according to Unicode code point) which is why I have toLowerCase(). The problem the above implementation does not solve is that "10abc" will come before "9abc".

Solution 8 - Javascript

Simply do:

array.sort((a,b)=>a[1]-b[1])

Replace 1 inside the brackets depending on the index based on which you need sorting.

To generalize, let me add the snippet below:

array.sort((a,b)=>a[i]-b[i])

I've seen many do this using a full function, which isn't necessary when a simple arrow function can do the job.

Keep it simple!

Thank you.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDojieView Question on Stackoverflow
Solution 1 - JavascriptcdhowieView Answer on Stackoverflow
Solution 2 - JavascriptRobGView Answer on Stackoverflow
Solution 3 - JavascriptPleaseStandView Answer on Stackoverflow
Solution 4 - Javascript19WAS85View Answer on Stackoverflow
Solution 5 - JavascriptpaulView Answer on Stackoverflow
Solution 6 - JavascriptabsView Answer on Stackoverflow
Solution 7 - JavascriptBoris YakubchikView Answer on Stackoverflow
Solution 8 - JavascriptVishwasR VibhuView Answer on Stackoverflow