Michael Joseph Aubry
Michael Joseph Aubry

Reputation: 13402

Finding the nearest number in an array of objects with multiple keys

I am not working with a flat array of numbers, I need context with the numbers i.e whether it's a start point or an endpoint.

I'm confused about how to evaluate which number is closest to a specific number.

const dataStructure = [{
  uid: "123",
  startTime: 2,
  endTime: 6
}, {
  uid: "345",
  startTime: 9,
  endTime: 15
}]

I'm tracking a node's coordinates on drag, when moving left the number to evaluate is its x coordinate, when moving right I am tracking the x coordinate plus the width. Either way, one number is produced and I am trying to evaluate which point is closest to my number. It can either be the startTime or the endTime.

But I need to know if it's start/end and the uid of the matching element.

I'm trying to put together in my head the logic for the reducer, but can't quite figure it out

const updatingTime = 6.7;

// TODO: Out of the two elements, which one is the closest, and which edge is the closest i.e start or end?
dataStructure.reduce((acc: any, curr: any) => {
  const lastEnd = acc.endTime;
  const lastStart = acc.startTime;
  const currEnd = curr.endTime;
  const currStart = curr.startTime;

  // find the node with either start or end closest to 6.7
  // also return key that was the best match i.e startTime/endTime

  return curr;
});

// if our number is 6.7 then uid: "123" is our answer with "end" being the edge

Upvotes: 0

Views: 92

Answers (2)

Michael Joseph Aubry
Michael Joseph Aubry

Reputation: 13402

Here is my solution following @bearacuda13's suggestion of simplifying the solution

const closest = ({ key, items }: any) =>
  items.reduce((acc: any, curr: any) =>
    Math.abs(curr[key] - updatingTime) < Math.abs(acc[key] - updatingTime) ? curr : acc
  );

const findClosestStart = closest({ key: "startTime", items: closestEls });
const findClosestEnd = closest({ key: "endTime", items: closestEls });
const a = Math.abs(findClosestStart.startTime - updatingTime);
const b = Math.abs(findClosestEnd.endTime - updatingTime);

const which = a < b ? findClosestStart : findClosestEnd;

console.log({ which });

Seems like this works not quite sure about performance and or edge cases.

Upvotes: 0

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48600

You can find the smallest distance by finding the minimum difference between the start or end time.

const data = [
  { uid: "123", startTime: 2, endTime:  6 },
  { uid: "345", startTime: 9, endTime: 15 }
];

const findClosest = (data, deltaFn, target) =>
  data.reduce((prev, curr) =>
    deltaFn(curr, target) - deltaFn(prev, target) < 0 ? curr : prev);

const minDiff = ({ startTime, endTime }, target) =>
  Math.min(Math.abs(startTime - target), Math.abs(endTime - target));

const closest = findClosest(data, minDiff, 6.7);

console.log(closest);
.as-console-wrapper { top: 0; max-height: 100% !important; }

Upvotes: 1

Related Questions