In our angularjs app we're receiving an array of dates that then need to be filtered out to only return an array full of unique dates (not strings). I tried some of the answers on SO but I think because I'm comparing dates and not strings - I'm yielding different results. Any help on what the best approach is would be very helpful.
2 Answers
You are right, date equality is different from string equality. Dates are objects, and the === comparator for objects compares them by reference, not value. Since {} === {} in JS is false, two Dates will never be equal to each other. So, let's just turn the dates into numbers:
let dates = [new Date(), new Date('1/1/11'), new Date('1/1/11'), new Date('1/4/66')]
let uniqueDates = dates
.map(s => s.getTime())
.filter((s, i, a) => a.indexOf(s) == i)
.map(s => new Date(s));
console.log(uniqueDates);
The logic with indexOf is that every unique value should be present only at its own position; any others are duplicates (s is current item, i is current index, and a is the array itself). Then we map the array back into Dates and return it.
2 Comments
.toString() with .getTime(). That returns the date as a simple number, epoch time. Cleaner and a little more efficient than comparing strings.If you're using lodash:
const date1 = new Date();
const date2 = new Date();
const arr = [date1, date1, date2, date2];
const uniqueDates = _.uniqBy(arr, date => date.getTime());
Uses uniqBy to ensure that we compare dates by their value and not just by object identity. See here: Compare two dates with JavaScript