83

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' },
];
JMP
  • 4,417
  • 17
  • 30
  • 41
Dojie
  • 831
  • 1
  • 6
  • 3

8 Answers8

104

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

RobG
  • 142,382
  • 31
  • 172
  • 209
101

(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;
}));
Drdilyor
  • 1,250
  • 1
  • 12
  • 30
cdhowie
  • 158,093
  • 24
  • 286
  • 300
16

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);
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
12

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;
    });
  });
};
19WAS85
  • 2,853
  • 1
  • 20
  • 19
6

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')));

paul
  • 1,124
  • 9
  • 27
  • 45
4

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));
});
abs
  • 801
  • 6
  • 15
1

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".

Boris Yakubchik
  • 3,861
  • 3
  • 34
  • 41
-4

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.

Toni
  • 1,555
  • 4
  • 15
  • 23
  • I think this is answering a different question. This answer is if a person wants to dynamically sort based on a property, in this case: "i". The OP wants to sort 2 distinct columns, on after the other, in a single sort call. – Sean Jan 22 '22 at 07:41