1

I'd like to sort this JavaScript array by three values, but I can't seem to figure out how to sort by more than one property at a time.

The requirements are:

  1. featured items should be at the very top
  2. Then items with no name (null)
  3. Then items with a name that are not featured
  4. Sort everything by createdAt in descending order (newest first)

This is the array:

var items [
    { name: 'foo-1', featured: true,  createdAt: 1493000001 },
    { name: null,    featured: false, createdAt: 1493000003 },
    { name: 'foo-3', featured: true,  createdAt: 1493000002 },
    { name: 'foo-4', featured: false, createdAt: 1493000004 },
    { name: 'foo-5', featured: false, createdAt: 1493000005 },
];

The result should be:

[
    { name: 'foo-3', featured: true,  createdAt: 1493000002 },
    { name: 'foo-1', featured: true,  createdAt: 1493000001 },
    { name: null,    featured: false, createdAt: 1493000003 },
    { name: 'foo-5', featured: false, createdAt: 1493000005 },
    { name: 'foo-4', featured: false, createdAt: 1493000004 },
]
Till
  • 1,107
  • 12
  • 28

2 Answers2

6

var items = [
    { name: 'foo-1', featured: true,  createdAt: 1493000001 },
    { name: null,    featured: false, createdAt: 1493000003 },
    { name: 'foo-3', featured: true,  createdAt: 1493000002 },
    { name: 'foo-4', featured: false, createdAt: 1493000004 },
    { name: 'foo-5', featured: false, createdAt: 1493000005 },
];

items.sort(function(a, b) {
    if(a.featured && !b.featured) return -1; // if a is featured and b is not, then put a above b
    if(!a.featured && b.featured) return 1;  // if b is featured and a is not, then put b above a
    
    if(!a.name && b.name) return -1;         // if a doesn't have a name and b does, then put a above b
    if(a.name && !b.name) return 1;          // if b doesn't have a name and a does, then put b above a
    
    return b.createdAt - a.createdAt;        // otherwise (a and b have simillar properties), then sort by createdAt descendently
});

console.log(items);
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73
1

You can use a compare function which can be passed as an argument to the sort() function - see Array.prototype.sort() for more detailed information. In your case the compare function may look like this:

var items = [
    { name: 'foo-1', featured: true,  createdAt: 1493000001 },
    { name: null,    featured: false, createdAt: 1493000003 },
    { name: 'foo-3', featured: true,  createdAt: 1493000002 },
    { name: 'foo-4', featured: false, createdAt: 1493000004 },
    { name: 'foo-5', featured: false, createdAt: 1493000005 },
];

function compare(a, b) {
    if (a.featured === true && b.featured === false) return -1;
    if (a.featured === false && b.featured === true) return 1;
    if (a.name === null && b.featured !== null) return -1;
    if (a.name !== null && b.name === null) return 1;

    return b.createdAt - a.createdAt;
};

items.sort(compare);

It should cover the case when the name is an empty string.

Mateusz Kleinert
  • 1,316
  • 11
  • 20