我需要以最接近的值获取数组中的对象。让我通过一个例子来解释它:
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{ age: 60, some: 'data' },
{ age: 66, something: 'else' },
{ age: 72 },
{ age: 78 },
{ age: 84 }
]
我确实使用data.find((d)=> d.age === 60)
获得了对象。但是如果年龄为61
,我不会得到结果。
在这种情况下,我想获得相同的对象。
对于64
,应返回下一个对象({ age: 66, something: 'else' }
)。
您可以看到年龄值不是线性的。
答案 0 :(得分:1)
以下是解决问题的完全抽象的方法:
// Saves up vertical space
const data = JSON.parse(`[{"age":52},{"age":53},{"age":54},{"age":60},{"age":66},{"age":72},{"age":78},{"age":84}]`);
function getClosestValue(list, getDifference) {
var smallestDiff = Infinity;
return list.reduce(function(closestValue, currentValue, index) {
var newDifference = Math.abs(getDifference(currentValue));
if (!index) return smallestDiff = newDifference, currentValue;
return smallestDiff = Math.min(smallestDiff, newDifference), newDifference === smallestDiff ? currentValue : closestValue;
});
}
function getClosestAge(list, age) {
return getClosestValue(list, function(listValue) {
return listValue.age - age;
});
}
console.log(getClosestAge(data, 65));
如果始终进行排序,则可以使用some
:
// Saves up vertical space
const data = JSON.parse(`[{"age":52},{"age":53},{"age":54},{"age":60},{"age":66},{"age":72},{"age":78},{"age":84}]`);
function getClosestValue(list, getDifference) {
var smallestDiff = Infinity;
var closestValue;
list.some(function(currentValue, index) {
var newDifference = Math.abs(getDifference(currentValue));
if (!index) return smallestDiff = newDifference, closestValue = currentValue, false;
if (smallestDiff > newDifference) return smallestDiff = newDifference, closestValue = currentValue, false;
else if (smallestDiff !== newDifference) return true;
});
return closestValue;
}
function getClosestAge(list, age) {
return getClosestValue(list, function(listValue) {
return listValue.age - age;
});
}
console.log(getClosestAge(data, 65));
答案 1 :(得分:1)
您可以找到所有数字之间的差,而最接近零的那个就是您的结果,要实现这一点,我将.reduce()
与Math.abs()
一起使用
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{ age: 60 },
{ age: 66 },
{ age: 72 },
{ age: 78 },
{ age: 84 }
];
const get_age = (data, to_find) =>
data.reduce(({age}, {age:a}) =>
Math.abs(to_find - a) < Math.abs(to_find - age) ? {age: a} : {age}
);
console.log(get_age(data, 61)); // {age: 60}
console.log(get_age(data, 50)); // {age: 52}
console.log(get_age(data, -1)); // {age: 52}
console.log(get_age(data, 90)); // {age: 84}
对于更一般化的对象(具有除age以外的其他属性),可以在分解时使用其余语法...
,然后将其重新散布到返回的对象中(再次使用...
):
const data = [
{ age: 52, id: 1},
{ age: 53, id: 2},
{ age: 54, id: 3},
{ age: 60, id: 4},
{ age: 66, id: 5},
{ age: 72, id: 6},
{ age: 78, id: 7},
{ age: 84, id: 8}
];
const get_age = (data, to_find) =>
data.reduce(({age, ...resto}, {age:a, ...rest}) =>
Math.abs(to_find - a) < Math.abs(to_find - age) ? {age: a, ...rest} : {age, ...resto}
);
console.log(get_age(data, 61)); // {age: 60, id: 4}
console.log(get_age(data, 50)); // {age: 52, id: 1}
console.log(get_age(data, -1)); // {age: 52, id: 1}
console.log(get_age(data, 90)); // {age: 84, id: 8}
答案 2 :(得分:0)
假设您的列表未排序,并且您不想对列表进行排序。因此,您可以选择第一个对象,遍历列表并检查是否有适合您需求的物品,而不是当前选择的物品。如果是这样,您只需用更好的产品代替。
例如
var data = [/*...*/];
var find_age = 64; // input
var best_item = data[0]; // pick any item as best item
for (var i = 1; i < data.length; i++) {
// does date[i] match the requirement better than best_item?
if (Math.abs (best_item.age - find_age) > Math.abs (data[i].age - find_age)) {
// it does ... so update best_item
best_item = data[i];
}
}
// best_item stores the item which matches your requirement most.
如果对数据集进行排序,则可以优化运行时间。
答案 3 :(得分:0)
您可以按查找年龄的不同对数组进行排序:
const lookupAge = 61
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{ age: 60 },
{ age: 66 },
{ age: 72 },
{ age: 78 },
{ age: 84 }
]
const result = data
.map(d => d.age)
.sort((a, b) => Math.abs(a - lookupAge) - Math.abs(b - lookupAge))
console.log('result', result)
答案 4 :(得分:0)
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{ age: 60 },
{ age: 66 },
{ age: 72 },
{ age: 78 },
{ age: 84 }
];
const find = 64;
const result = data.map(({ age }) => age).reduce((best, el, index) => {
if (Math.abs(find - el) < Math.abs(find - best)) {
return el;
}
return best;
}, data[0].age)
console.log(result)
答案 5 :(得分:0)
您可以通过从每个元素中减去给定数字并取绝对值来找到最小差异,然后进行较高查找和较低查找
它还将考虑何时存在两个不同的最接近值
const data = [
{ age: 52 },
{ age: 53 },
{ age: 55 },
{ age: 60 },
{ age: 66 },
{ age: 72 },
{ age: 78 },
{ age: 84 }
]
function minimum(given){
//let given=54
//find the mimimun different
let closest_diff=Math.min(...data.map(a=>Math.abs(a.age-given)))
//for lower closest number
let x1=data.find(a=>a.age===given-closest_diff);
//for highter closest number
let x2=data.find(a=>a.age===given+closest_diff);
//filter the number which are in array above
console.log(...new Set([x1,x2].filter(x=>x)));
}
minimum(52); //52
minimum(54); //53 and 55
minimum(63); //60 and 66
minimum(75); //72 and 78
minimum(77); //78
答案 6 :(得分:0)
对于排序后的数据,您可以将具有最大值的数据作为起始值,从头开始进行迭代,并在增量增加时停止迭代。
var data = [{ age: 52 }, { age: 53 }, { age: 54 }, { age: 60 }, { age: 66 }, { age: 72 }, { age: 78 }, { age: 84 }],
result = data[data.length - 1],
age = 61;
data.some((o) => {
if (Math.abs(age - o.age) >= Math.abs(age - result.age)) return true;
result = o;
});
console.log(result);
答案 7 :(得分:0)
我做了一个小小的代码段,向您展示了我这样做的方式。这样可以在需要属性名称和值的任何对象数组上使用findClosest
方法。然后,该函数将返回具有最接近给定属性值的数组元素。可以改进,但是效果很好。
document.addEventListener("DOMContentLoaded", function() {
const listElem = document.getElementById('list');
const closestElem = document.getElementById('closest');
data.forEach(elem => {
const listElemEntry = document.createElement('li');
listElemEntry.innerHTML = elem.age;
listElem.appendChild(listElemEntry);
});
const closest = data.findClosest('age', 80);
closestElem.innerHTML = closest;
});
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{ age: 60 },
{ age: 66 },
{ age: 72 },
{ age: 78 },
{ age: 84 }
];
Array.prototype.findClosest = function(attr, value) {
const closestElem = { diff: Infinity, index: -1 };
this.forEach((elem, index) => {
const diff = Math.abs(elem[attr] - value);
if (diff < closestElem.diff) {
closestElem.diff = diff;
closestElem.index = index;
}
});
return this[closestElem.index][attr];
}
<h2>Elements list</h2>
<ul id="list"></ul>
<h2>Closest element</h2>
<pre id="closest"></pre>
答案 8 :(得分:0)
您可以找到具有最小差异的数组的最接近项,如下所示;
function getClosest(data, x) {
if (data.length == 0) {
return null;
}
var index = 0;
var difference = Number.MAX_SAFE_INTEGER;
for(var i = 0; i<data.length;i++) {
if (i < data.length) {
var differ = Math.abs(data[i].age - x);
if(differ < difference) {
difference = differ;
index = i;
}
}
}
return data[index];
}
用法:
getClosest(data, 64)
答案 9 :(得分:0)
Suppose array isn't sorted. Following function returns result. If it find value that is equal to search value, it stops searching, so it is a small gain in performance.
function minDiff(data, val) {
let res = null;
let n = data.length;
let diffGet = (val1, val2) => Math.abs(val1 - val2);
if (n>0) {
res = data[0];
let diff = diffGet(res.age, val);
let i = 1;
while ( diff>0 && i<n ) {
if (diffGet(data[i].age, val) < diff) {
res = data[i];
diff = diffGet(res.age, val);
}
i++;
}
}
return res;
}
答案 10 :(得分:0)
这是解决问题的一种实用方法:
const data = [
{ age: 52 },
{ age: 53 },
{ age: 54 },
{
age: 60,
some: "data"
},
{
age: 66,
something: "else"
},
{ age: 72 },
{ age: 78 },
{ age: 84 }
];
const indexOfSmallest = (array) => {
if (array.length === 0) {
throw new Error("Empty array, expects at least one element");
}
return array.reduce((lowest, next, index) => {
if (next < array[lowest]) {
return index;
}
return lowest;
}, 0);
};
const getClosestIndex = (numbers, referenceNumber) => {
const diff = numbers.map(n => Math.abs(referenceNumber - n));
return indexOfSmallest(diff);
};
const createGetClosestIndex = (numbers) => (number) => getClosestIndex(numbers, number);
const createGetClosestPerson = (people) => {
return (targetAge) => {
const numbers = people.map(d => d.age);
const index = createGetClosestIndex(numbers)(targetAge);
return people[index];
};
};
const getClosest = createGetClosestPerson(data);
console.log(getClosest(1), getClosest(64));