Skip to content
Advertisement

Get the nearest object key from object containing multiple objects with numeric keys

I have an object containing an undefined number of child objects which are associated by numeric values as the object keys. What I need is a way to pass in a numeric number (currency) and get the child object that is the closest to the number I pass into the function.

Example Object structure

{
"32.5": [
{
  "key": "value",
  "key": "value"
},
{
  "key": "value",
  "key": "value"
}
],
"34": [
{
  "key": "value",
  "key": "value"
}
],
"35.5": [
{
  "key": "value",
  "key": "value"
}
]
}

The keys of the object are strings, so I already figured out I probably somehow have to parse the object keys to a number for comparison but I am completely lost on how to tie it all together.

I declared a function that takes 3 parameters which at the end should return the child object where its key is the closest to my input parameter.

function getNearest(obj, decimalNumber, below_or_above)

when I put in “above” I want to get the closest key where its number value is the next higher, when I put in “below” it would return the next object where its number key is the next smaller.

If I would call getNearest(obj, 33.4, above) it should return the object with the key “34”.

I hope I managed somehow to explain so everyone can understand..

This is the starting point I came up with but I don’t know how to proceed from here

    function getNearest(obj, decimalNumber, above_or_below){
    const keys = [];
    Object.keys(obj).forEach(key =>{
        let numericKey = Number(key);
        keys.push(numericKey);
    })

    //store all numeric keys in array to further process later on
    }

Advertisement

Answer

  • Transform the object into an array of items using Object.entries.
  • Loop over the object using Array.prototype.map and convert the string keys to numbers, to perform comparisons correctly.
  • Sort the array by the keys using Array.prototype.sort.
  • Find the key based on the pos argument using Array.prototype.find.
  • Finally return the value corresponding to the found key.

const 
  data = { 32.5: [{ key: "32.5" }], 34: [{ key: "34" }], 35.5: [{ key: "35.5" }] },
  getKey = (obj, target, pos) =>
    Object.entries(obj)
      .map(([k, v]) => [Number(k), v])
      .sort(([a], [b]) => a - b)
      .find(([k], i, a) =>
        pos === "above"
          ? k >= target
          : k <= target && (a[i + 1]?.[0] > target || i === a.length - 1)
      )?.[1];

console.log(getKey(data, 33, "above")); // [{ key: "34" }]
console.log(getKey(data, 33, "below")); // [{ key: "32.5" }]
console.log(getKey(data, 37, "above")); // undefined
console.log(getKey(data, 30, "below")); // undefined

Table for reference:

target below above
0 undefined [{ key: '32.5' }]
31.4 undefined [{ key: '32.5' }]
32.5 [{ key: '32.5' }] [{ key: '34' }]
32.8 [{ key: '32.5' }] [{ key: '34' }]
33.4 [{ key: '32.5' }] [{ key: '34' }]
34 [{ key: '34' }] [{ key: '34' }]
35.1 [{ key: '34' }] [{ key: '35.5' }]
35.5 [{ key: '35.5' }] [{ key: '35.5' }]
50 [{ key: '35.5' }] undefined
Advertisement