Reputation: 437
I'm trying to find the highest date among an array of objects with varying dates that will be attributed to each object. The code works great as long as the dates are above Jan 1st 1970, but any date before that causes error. How can I fix it with keeping the same dates obviously? I know I could use get(Time) on all the dates but is there any way around that? Thanks.
var playerData = [
{name: "John"},
{name: "Bill"},
{name: "Bob"},
{name: "Jim"},
];
var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);
playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;
function findHighDate() {
var highDateSoFar = null;
var result;
for (var i = 0; i < playerData.length; i++) {
if (playerData[i].date > highDateSoFar) {
result = playerData[i];
highDateSoFar = playerData[i].date;
}
else if (playerData[i].date === highDateSoFar) {
result = 'equal';
}
}
return result;
}
var highPlayer = findHighDate();
var highPlayerName = highPlayer.name;
var highPlayerIndex = playerData.indexOf(highPlayer);
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});
Upvotes: 0
Views: 130
Reputation: 13964
Instead of comparing dates, you could compare the strings and use Array.sort
to order them in decreasing order, then get the first item:
const playerData = [
{name: "John", date: '1940-02-05' },
{name: "Bill", date: '1950-06-18' },
{name: "Bob", date: '1650-07-12' },
{name: "Jim", date: '1300-03-25' },
];
function findHighDate() {
return playerData.sort((a, b) => b.date.localeCompare(a.date))[0];
}
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = new Date(highPlayer.date);
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });
Or you can also stick with dates and compare them using Date.getTime()
for sorting your array:
const playerData = [
{name: "John", date: new Date('1940-02-05') },
{name: "Bill", date: new Date('1950-06-18') },
{name: "Bob", date: new Date('1650-07-12') },
{name: "Jim", date: new Date('1300-03-25') },
];
function findHighDate() {
return playerData.sort((a, b) => b.date.getTime() - a.date.getTime())[0];
}
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = highPlayer.date;
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });
As @Scott Sauyet pointed out in the comments below, using Array.sort
may be overkill for your scenario.
You can find your highest date with a bit more code and the help of reduce
:
const playerData = [
{name: "John", date: new Date('1940-02-05') },
{name: "Bill", date: new Date('1950-06-18') },
{name: "Bob", date: new Date('1650-07-12') },
{name: "Jim", date: new Date('1300-03-25') },
];
function findHighDate() {
return playerData.reduce((highest, player) => {
return highest.date.getTime() > player.date.getTime() ? highest : player;
}, playerData[0]);
}
const highPlayer = findHighDate();
const highPlayerName = highPlayer.name;
const highPlayerIndex = playerData.indexOf(highPlayer);
const highPlayerDate = highPlayer.date;
console.log({ highPlayer, highPlayerIndex, highPlayerName, highPlayerDate });
Upvotes: 1
Reputation: 50787
I often find it's easier to solve a problem by moving up a level or two of abstraction. If we want to find the object that has the highest date property, I might start by writing something that finds the maximum by any given property. But even better, I could supply it with a function and find the value which maximizes that function. It turns out that this is just as easy to write as the date one, and it separates out the logic of finding the maximum from the mundane bit of choosing the date property.
So here we could write
const maximumBy = (fn) => (data) =>
data.reduce((m, x) => fn(x) > fn(m) ? x : m, data[0])
const findHighestPlayer = maximumBy(player => player.date)
var playerData = [
{name: "John", date: new Date(1940, 2, 5)},
{name: "Bill", date: new Date(1950, 6, 18)},
{name: "Bob", date: new Date(1650, 7, 12)},
{name: "Jim", date: new Date(1300, 3, 25)},
];
console.log(findHighestPlayer(playerData))
Note that if your array is empty, this will return undefined
, but it's hard to know what else to do. You could always add a default value parameter if that's important to fix.
Upvotes: 0
Reputation: 147343
Using >
for coersion to number works most of the time, however when comparing to numbers null evaluates to 0, so negative numbers are less than null.
So just avoid that comparison either by initialising highDateSoFar to some other value (e.g. -Infinity or the first date in the array), or test for it being null, e.g.
var playerData = [
{name: "John", date: new Date(1940, 2, 5)},
{name: "Bill", date: new Date(1950, 6, 18)},
{name: "Bob", date: new Date(1650, 7, 12)},
{name: "Jim", date: new Date(1300, 3, 25)},
];
function findHighDate(data) {
var highDateSoFar = null;
var result;
for (var i=0; i < data.length; i++) {
if (highDateSoFar === null || data[i].date > highDateSoFar) {
result = data[i];
highDateSoFar = data[i].date;
}
}
return result ;
}
console.log( findHighDate(playerData) );
Also the expression playerData[i].date === highDateSoFar
will only be true if playerData[i].date and highDateSoFar reference the same Date object, which can't be true in the logic of the function.
You can use reduce for this too:
var playerData = [
{name: "John", date: new Date(1940, 2, 5)},
{name: "Bill", date: new Date(1950, 6, 18)},
{name: "Bob", date: new Date(1650, 7, 12)},
{name: "Jim", date: new Date(1300, 3, 25)},
];
function getHighest(data) {
return data.reduce((acc, high) => {
acc = high.date > acc.date? high : acc;
return acc;
}, {date:-Infinity});
}
console.log(getHighest(playerData));
Upvotes: 0
Reputation: 691
You can do this. I have simplified the logic. You can use the sort() too, like others have suggested.
var playerData = [
{name: "John"},
{name: "Bill"},
{name: "Bob"},
{name: "Jim"},
];
var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);
playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;
function playerWithHighestDate() {
// start by assuming player 0 is highest
var winner = 0;
// start at one as we dont need to compare with player 0
for (var i = 1; i < playerData.length; i++) {
// compares players date
if (playerData[i].date >= playerData[winner].date) {
winner = i;
}
}
// returns the winner index
return winner;
}
// get index with highest date
var highPlayerIndex = playerWithHighestDate();
var highPlayer = playerData[highPlayerIndex];
var highPlayerName = highPlayer.name;
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});
Upvotes: 0
Reputation: 33141
If you use getTime()
on the dates, the ones prior to 1970 will simply be negative, so usual math comparisons work fine. Below I simply sort your player datas by date (max first). If you want the highest, just grab the first item in the array:
var playerData = [
{name: "John"},
{name: "Bill"},
{name: "Bob"},
{name: "Jim"},
]
playerData[0].date = new Date(1940, 02, 05)
playerData[1].date = new Date(1950, 06, 18)
playerData[2].date = new Date(1650, 07, 12)
playerData[3].date = new Date(1300, 03, 25)
playerData.sort((a, b) => b.date.getTime() - a.date.getTime())
console.log(playerData)
Upvotes: 0
Reputation: 11
You can pre assign the first person's date to do the comparison like this.
var playerData = [
{name: "John"},
{name: "Bill"},
{name: "Bob"},
{name: "Jim"},
];
var dateOne = new Date(1940,02,05);
var dateTwo = new Date(1950, 06,18);
var dateThree = new Date(1650,07,12);
var dateFour = new Date(1300, 03,25);
playerData[0].date = dateOne;
playerData[1].date = dateTwo;
playerData[2].date = dateThree;
playerData[3].date = dateFour;
function findHighDate() {
console.log(playerData);
var highDateSoFar = playerData[0].date;
var result = playerData[0];
for (var i = 0; i < playerData.length; i++) {
if (playerData[i].date > highDateSoFar) {
result = playerData[i];
highDateSoFar = playerData[i].date;
}
else if (playerData[i].date === highDateSoFar) {
}
}
return result;
}
var highPlayer = findHighDate();
var highPlayerName = highPlayer.name;
var highPlayerIndex = playerData.indexOf(highPlayer);
var highPlayerDate = highPlayer.date;
console.log({highPlayer},{highPlayerIndex},{highPlayerName},{highPlayerDate});
Upvotes: 0