Sorting an Array of JavaScript Objects by Date

 Sorting an Array of JavaScript Objects by Date

In JavaScript, arrays are one of the most common data structures you will work with, and from time to time, you might find the need to sort them. The Array.prototype.sort() method is the built-in JavaScript function that helps us sort the elements of an array. By default, this function sorts arrays lexicographically (alphabetically) based on the string conversion of each element.

However, what if we want to sort an array of objects based on a date field? Let's take an array of alert objects for example, where each alert object has a createdon field representing the date it was created. We can utilize the sort() method and provide a custom comparator function to sort these objects.

Here's how:

alerts.sort(function(a, b) { return new Date(a.createdon) - new Date(b.createdon); });

What's happening here?

Firstly, sort() is called on the alerts array. sort() takes a function as an argument, which dictates the sort order. This function is often referred to as a "compare function".

Our compare function takes two arguments, a and b. These represent two elements in the array that sort() is comparing during the sorting process.

Within the compare function, we're converting the createdon properties of a and b to JavaScript Date objects using the new Date() constructor. This constructor creates a new Date object from a date string.

When we subtract one Date object from another (i.e., new Date(a.createdon) - new Date(b.createdon)), the operation returns the difference in milliseconds between the two dates. This value can be:

  • A negative number if a.createdon is earlier than b.createdon (meaning a should come before b in the sorted array)
  • Zero if a.createdon and b.createdon represent the same point in time (meaning the order of a and b does not matter)
  • A positive number if a.createdon is later than b.createdon (meaning a should come after b in the sorted array)

In this way, our alerts array gets sorted in ascending order of createdon, i.e., earlier alerts come first.

If you want to sort the array in descending order based on the createdon field, you simply need to subtract a.createdon from b.createdon in your compare function. Here's how you would do it:

alerts.sort(function(a, b) { return new Date(b.createdon) - new Date(a.createdon); });


Conclusion

1. If sort function return negative value, no change.

2. If return 0, no change.

3. If return positive value, switch the order.


Another examples:

Reference: 1

Sorting based on the content of the string

Let's go one step further and say we had a bunch of attendees at a seminar, and we want to list them all out for a register. But we want all the Doctors to be listed at the top, as these are the keynote speakers.

We can do this with a custom comparison function:

const names = ["Mike Smith", "Dr. Johnson", "John Doe", "Dr. Williams"];

names.sort((a, b) => {
  if (a.startsWith("Dr.") && !b.startsWith("Dr.")) {
    return -1;
  } else if (!a.startsWith("Dr.") && b.startsWith("Dr.")) {
    return 1;
  } else {
    return a.localeCompare(b); // sort alphabetically
  }
});

console.log(names);

// Output:
["Dr. Johnson", "Dr. Williams", "John Doe", "Mike Smith"];

So above, we're stating that if the string begins with "Dr" and the next value doesn't start with "Dr" then it should go before the right value, and then vice versa for the 2nd if statement.

If neither values for comparison have "Dr" in them, then the function will utilise the localCompare function. This essentially reverts back to the default Unicode comparison as discussed earlier in this article.

Strings of Numbers and Letters

Suppose you want to sort an array that contains both numbers and letters. You want the numbers to appear before the letters, and within each group, you want the elements to be sorted numerically and alphabetically, respectively. Here's how you can achieve that:

const items = ["b", "3", "a", "2", "c", "1"];

items.sort((a, b) => {
  const aIsNumber = !isNaN(a); // isNaN = is Not a Number
  const bIsNumber = !isNaN(b);

  if (aIsNumber && !bIsNumber) {
    return -1; // numbers should be sorted before letters
  } else if (!aIsNumber && bIsNumber) {
    return 1; // letters should be sorted after numbers
  } else if (aIsNumber && bIsNumber) {
    return a - b; // sort numbers numerically
  } else {
    return a.localeCompare(b); // sort letters alphabetically
  }
});

console.log(items);

// Output
["1", "2", "3", "a", "b", "c"];


No comments:

Post a Comment