Reputation: 23
I have an object array which looks like this
var OGArray = [
{ time: '16:33:53', import_today: '1.10' },
{ time: '16:28:20', import_today: '1.10' },
{ time: '16:23:07', import_today: '1.10' }]
The time automatically updates from an API. I also have an array that looks like this
var timeArray = ['16:00:00', '16:30:00', '17:00:00', '17:30:00']
I want to be able to look at the timeArray[0] and find the closest time match from OGArray.time and then pull what the import_today is
Upvotes: 1
Views: 893
Reputation: 147343
You can use a small helper to convert time to a common base, say seconds, then compare the absolute differences between the times in the two arrays. Array.prototype.reduce can help to get the one with the lowest difference.
I don't know how you intend to call this or what actual result you want, but here's one way to get the closest object in OGArray for each element in timeArray. Once you have the closest object, you can do what you want with it.
It's a little more efficient than using a Date object, but loops through every element in OGArray for each element in timeArray. If the elements are sorted, then it can be optimised a little by using a loop instead of reduce and breaking as soon as diff starts to increase.
If OGArray is really large (say more than 1,000 elements) and sorted by time, you might use a binary search to find the closest element. That way you do no more than 10 to 20 searches even if the array is 1,000,000 elements or so.
function timeToSecs(time) {
let [h, m, s] = time.split(':');
return h*3.6e3 + m*60 + s*1;
}
var OGArray = [
{ time: '16:33:53', import_today: '1.10' },
{ time: '16:28:20', import_today: '1.10' },
{ time: '16:23:07', import_today: '1.10' }
];
var timeArray = ['16:00:00', '16:30:00', '17:00:00', '17:30:00']
// For each element in timeArray
timeArray.forEach(time => {
let secs = timeToSecs(time);
let closest = null;
// Find closest element in OGArray
OGArray.reduce((acc, obj, i) => {
let diff = Math.abs(timeToSecs(obj.time) - secs);
if (diff < acc) {
acc = diff;
closest = obj;
}
return acc;
}, Number.POSITIVE_INFINITY);
// Display result
console.log('Time : ' + time +
'\nClosest: ' + JSON.stringify(closest));
});
Upvotes: 1
Reputation: 207501
It is just a loop over and you do the calculation to what time is closer and you store it. Pick the one that is less.
Below is not the most efficient code, but it works.
var OGArray = [
{ time: '16:33:53', import_today: '1.10' },
{ time: '16:28:20', import_today: '1.10' },
{ time: '16:23:07', import_today: '1.10' }]
var timeArray = ['16:00:00', '16:30:00', '17:00:00', '17:30:00']
var closestArray = timeArray.map(t => {
const ts = new Date(`01/01/2022 ${t}`);
return OGArray.reduce((closest, item) => {
const dC = Math.abs(new Date(`01/01/2022 ${closest.time}`) - ts);
const dI = Math.abs(new Date(`01/01/2022 ${item.time}`) - ts);
return dC < dI ? closest : item;
});
})
console.log(closestArray);
Upvotes: 1