JavaScript - sort to do list by date then status

Viewed 447

I have a to do list that I need to sort by dueDate and by status (incomplete => complete). The incomplete tasks should be in ASC order by dueDate. Then the completed tasks should come after incomplete tasks and they should also be in ASC order by dueDate.

unsorted array 
[{"task":"Dishes", "isComplete":false, "dueDate":"2021-01-01T15:45:00.000Z"},{"task":"feed baby", "isComplete":true, "dueDate":"2021-01-02T15:45:00.000Z"},{"task":"Laundry", "isComplete":true, "dueDate":"2021-01-04T15:45:00.000Z"},{"task":"Homework", "isComplete":false, "dueDate":"2021-01-03T15:45:00.000Z"}]

sorted array
    [
    {
    "task":"Dishes",
    "isComplete":false,
    "dueDate":"2021-01-01T15:45:00.000Z"
    },
    {
    "task":"Homework",
    "isComplete":false,
    "dueDate":"2021-01-03T15:45:00.000Z"
    }
    {
    "task":"feed baby",
    "isComplete":true,
    "dueDate":"2021-01-02T15:45:00.000Z"
    },
    {
    "task":"Laundry",
    "isComplete":true,
    "dueDate":"2021-01-04T15:45:00.000Z"
    },
    ]

Here is my approach using 2 sort functions, first by date then by status but I feel it can be reduced further:

const sortByDate = (a,b) => {
    if (new Date(a.dueDate) < new Date(b.dueDate)){
        return -1;
    }
    if (new Date(a.dueDate) > new Date(b.dueDate)) {
        return 1;
    }
    return 0;
}
const sortByStatus = (a,b) => {
    if (a.isComplete < b.isComplete){
        return -1;
    }
    if (a.isComplete > b.isComplete) {
        return 1;
    }
    return 0;
}
5 Answers

You can use the coercive property of subtraction and the logical OR operator.

const arr = [{"task":"Dishes", "isComplete":false, "dueDate":"2021-01-01T15:45:00.000Z"},{"task":"feed baby", "isComplete":true, "dueDate":"2021-01-02T15:45:00.000Z"},{"task":"Laundry", "isComplete":true, "dueDate":"2021-01-04T15:45:00.000Z"},{"task":"Homework", "isComplete":false, "dueDate":"2021-01-03T15:45:00.000Z"}];
arr.sort((a,b) => a.isComplete - b.isComplete || new Date(a.dueDate) - new Date(b.dueDate));
console.log(arr);

If you are asking for a combined sort function. Then this should do the work

const sortArray = (a,b) => {
    if (new Date(a.dueDate) < new Date(b.dueDate)){
        return -1;
    }
    else if (new Date(a.dueDate) > new Date(b.dueDate)) {
        return 1;
    }
    else {  // This else means, due date is same, and we need to consider the status in this case
        if (b.isComplete){
            return 1;
        }
        else if (a.isComplete) {
            return -1;
        }
        return 0; // This means status and due date are equal
    }
};

First this will sort by the due date. If the due dates are equal, then the status will be considered for such elements.

array.sort((a, b) => {
  return sortByStatus(a,b) || sortByDate(a, b);
});

More descriptive

array.sort((a, b) => {
  const byStatus = sortByStatus(a, b)
  // if status isn't same, compare by status
  if( byStatus !== 0 ) return byStatus;
  // else compare by date
  return sortByDate(a,b);
});

try this.

unsorted_arr =
[{"task":"Dishes", "isComplete":false, "dueDate":"2021-01-01T15:45:00.000Z"},{"task":"feed baby", "isComplete":true, "dueDate":"2021-01-02T15:45:00.000Z"},{"task":"Laundry", "isComplete":true, "dueDate":"2021-01-04T15:45:00.000Z"},{"task":"Homework", "isComplete":false, "dueDate":"2021-01-03T15:45:00.000Z"}];

unsorted_arr.sort(function (a, b) {
    if(a.isComplete == b.isComplete)
        return (a.dueDate < b.dueDate) ? -1 : (a.dueDate > b.dueDate) ? 1 : 0;
    else
        return (a.isComplete < b.isComplete) ? -1 : 1;
});
console.log(unsorted_arr);

Try this one:

var array = [{"task":"Dishes", "isComplete":false, "dueDate":"2021-01-01T15:45:00.000Z"},{"task":"feed baby", "isComplete":true, "dueDate":"2021-01-02T15:45:00.000Z"},{"task":"Laundry", "isComplete":true, "dueDate":"2021-01-04T15:45:00.000Z"},{"task":"Homework", "isComplete":false, "dueDate":"2021-01-03T15:45:00.000Z"}]

var newarray = array.sort((a, b) => {
  const date = new Date(a.dueDate) - new Date(b.dueDate);
  const isComplete = a.isComplete - b.isComplete;

  return isComplete || date ;
})

console.log(newarray);

Related