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
}
CodePudding user response:
- 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 |
CodePudding user response:
You could
- get keys from the object,
- map numbers,
- sort array to adjust native object sorting (positev 32 bit integer first),
- find the value by check if smaller than value or hitting last item or if the absolute delta of actual and next item is smaller.
value below above
------- ------- -------
0 undef 32.5
31.4 undef 32.5
32.5 32.5 34
32.8 32.5 34
33.4 32.5 34
34 34 34
35.1 34 35.5
35.5 35.5 35.5
50 35.5 undef
isAbove false true
const
getKey = (object, value, isAbove) => Object
.keys(object)
.map(Number)
.sort((a, b) => a - b)
.find((v, i, a) => isAbove
? v >= value
: v <= value && (a[i 1] > value || i 1 === a.length)
),
data = { 32.5: [{}], 34: [{}], 35.5: [{}] };
console.log('below');
console.log(getKey(data, 0)); // 32.3
console.log(getKey(data, 31.4)); // 32.3
console.log(getKey(data, 32.5)); // 32.3
console.log(getKey(data, 32.8)); // 32.3
console.log(getKey(data, 33.4)); // 34
console.log(getKey(data, 34)); // 34
console.log(getKey(data, 35.1)); // 35.5
console.log(getKey(data, 35.5)); // 35.5
console.log(getKey(data, 100)); // 35.5
console.log('above');
console.log(getKey(data, 0, true)); // 32.3
console.log(getKey(data, 31.4, true)); // 32.3
console.log(getKey(data, 32.5, true)); // 32.3
console.log(getKey(data, 32.8, true)); // 32.3
console.log(getKey(data, 33.4, true)); // 34
console.log(getKey(data, 34, true)); // 34
console.log(getKey(data, 35.1, true)); // 35.5
console.log(getKey(data, 35.5, true)); // 35.5
console.log(getKey(data, 100, true)); // 35.5
.as-console-wrapper { max-height: 100% !important; top: 0; }