简体   繁体   English

在数组中找到最接近给定数字的数字

[英]Find the number in an array that is closest to a given number

I have an Array of integers in javascript, [5,10,15,20,25,30,35] when given a number x, how can I find the element in the array that is closest to that number?我在 javascript 中有一个整数数组, [5,10,15,20,25,30,35]当给定一个数字 x 时,如何在数组中找到最接近该数字的元素?

If the number is over a value, but less than halfway to the next number, I would choose the smaller value, if it were over halfway to the next number, I would choose the higher number.如果数字超过一个值,但小于下一个数字的一​​半,我会选择较小的值,如果它超过下一个数字的一​​半,我会选择较大的数字。

For example 7 would return 5, but 8 would return 10. How can I accomplish this?例如 7 将返回 5,但 8 将返回 10。我怎样才能做到这一点? Any help or tips would be appreciated.任何帮助或提示将不胜感激。 I have searched and cannot find a solution.我已经搜索过,但找不到解决方案。 I'm sure this is sort of common.我确定这很常见。

Probably the easiest thing to do is sort based on distance from the reference value x, and then take the first item.可能最简单的方法是根据与参考值 x 的距离进行排序,然后取第一项。

The built-in Array.prototype.sort() can take a comparison function which will be called for pairs of values from the array.内置的Array.prototype.sort()可以采用一个比较函数,该函数将被调用以获取数组中的值对。 Then the key is simply to pass in a comparison function which compares the two values based on their distance from the reference value x.然后关键是简单地传入一个比较函数,该函数根据两个值与参考值 x 的距离进行比较。

let x = 8;
let array = [5, 10, 15, 20, 25, 30, 35];
let closest = array.sort( (a, b) => Math.abs(x - a) - Math.abs(x - b) )[0];

See this simple demo .请参阅这个简单的演示

function getClosest(array, target) {
    var tuples = _.map(array, function(val) {
        return [val, Math.abs(val - target)];
    });
    return _.reduce(tuples, function(memo, val) {
        return (memo[1] < val[1]) ? memo : val;
    }, [-1, 999])[0];
}

If using a functional approach is applicable then you can map the set to tuples of (value, distance) then reduce that set of tuples to the tuple with the smallest distance.如果使用函数方法适用,那么您可以将集合映射到 (value, distance) 的元组,然后将该元组集合减少到距离最小的元组。 We return the value in that tuple.我们返回该元组中的值。

To explain the useage of _.map .解释_.map You map all the values in your array to new values and the function will return the array of new values.您将数组中的所有值映射到新值,该函数将返回新值数组。 In this case an array of tuples.在这种情况下,一个元组数组。

To explain the useage of _.reduce .解释_.reduce You reduce the array to a single value.您将数组减少为单个值。 You pass in an array and a memo.你传入一个数组和一个备忘录。 The memo is your "running counter" as you move through the array.当您在阵列中移动时,备忘录是您的“运行计数器”。 In this case we check whether the current tuple is closer then the memo and if so make it the memo.在这种情况下,我们检查当前元组是否比备忘录更接近,如果是,则将其设为备忘录。 We then return the memo at the end.然后我们在最后返回备忘录。

The code snippet above relies on underscore.js to remove the nitty gritty of functional style javascript上面的代码片段依赖underscore.js来删除函数式 javascript 的细节

Your example list is sorted.您的示例列表已排序。 If this is always the case, then binary search for your number.如果总是这样,那么二进制搜索你的号码。 If you don't find the exact number, make the binary search end off by checking the two numbers around where the number would be and return the closest.如果你没有找到确切的数字,通过检查各地,其中人数并返回最接近的两个数字让二进制搜索结束了。 Be careful with edge cases where all numbers are greater or are all smaller than the target number小心所有数字都大于或小于目标数字的边缘情况

If the list isn't always sorted, then go through the list keeping track of the largest number <= the target number and the smallest number >= the target number.如果列表并不总是排序,然后通过列表跟踪最大数 <= 目标数和最小数 >= 目标数。 Return the one that's closest to the target.返回最接近目标的那个。

In either solution, you'll need to decide which side to favour if for example you're searching for 2 in [1, 3].在任一解决方案中,例如,如果您在 [1, 3] 中搜索 2,您都需要决定偏爱哪一边。

Create a temporary array of the same size as your original array, and populate it with the differences between your x and the array element.创建一个与原始数组大小相同的临时数组,并用 x 和数组元素之间的差异填充它。

For example, let the temporary array be temp[], and your original array be a[]:例如,让临时数组为 temp[],而您的原始数组为 a[]:

temp[i]=Math.abs(x-a[i]);

Then, return the index of the minimum value in temp[] to the user.然后,将 temp[] 中最小值的索引返回给用户。

I created my own function since i could not find any that meets my requeriments.我创建了自己的函数,因为我找不到任何满足我的要求的函数。

    function closest_number(quantities, number, closest_factor)
    {
        if (closest_factor == 'ceil')
        {
            quantities.sort(function(a, b)
                {
                    return a - b
                }
            );

            for (var i = 0; i < quantities.length; i++)
            {
                if (quantities[i] >= number)
                {
                    return quantities[i];
                }

                last_value = quantities[i];
            }

            return last_value;
        }
        else if (closest_factor == 'floor')
        {
            quantities.sort(function(a, b)
                {
                    return a - b
                }
            );

            min_value = quantities[0];

            for (var i = 0; i < quantities.length; i++)
            {
                if (number == quantities[i])
                {
                    return number;
                }
                else if (quantities[i] < number)
                {
                    min_value = quantities[i];
                }
                else if(quantities[i] > number)
                {
                    return min_value;
                }           
            }

            return min_value;
        }
        else
        {
            return false;
        }
    };

Assuming the array is sorted, step through each adjacent pair of integers in the array.假设数组已排序,请逐步遍历数组中的每对相邻整数。 For each pair (say "5 and 10" or "20 and 25"), test if x is in between them, and if so, return whichever one is closer to x (with a bias towards the lower one).对于每一对(比如“5 和 10”或“20 和 25”),测试x是否在它们之间,如果是,则返回更接近x 的那个(偏向于较低的那个)。

You would also need a special case for when x is less than the first number (return the first number) or greater than the last number (return the last number).x小于第一个数字(返回第一个数字)或大于最后一个数字(返回最后一个数字)时,您还需要一个特殊情况。

If the array is not sorted, sort it first.如果数组没有排序,先排序。

Since Array.reduce is a reality for so long ( even IE9 supports it ), the problem is easily solvable with it.由于Array.reduce已经存在了这么久(即使 IE9 也支持它),问题很容易用它解决。 This way, no need to sort the array first (no array mutation at all):这样,不需要先对数组进行排序(根本没有数组突变):

 var numbers = [20, 25, 30, 35, 5, 10, 15], x = 7; var output = numbers.reduce(function (prev, curr) { return Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev }); console.log(output);

You can go further and solve it with only one line of ES6 (ECMAScript 2015) syntax, by using an arrow function (but with no IE support in this case):您可以更进一步,通过使用箭头函数(但在这种情况下不支持 IE ),仅使用一行 ES6 (ECMAScript 2015) 语法来解决它:

 const numbers = [20, 25, 30, 35, 5, 10, 15], x = 7; const output = numbers.reduce((prev, curr) => Math.abs(curr - x) < Math.abs(prev - x) ? curr : prev); console.log(output);

Of course, for flexibility and reusability, it's easy to make it as a function:当然,为了灵活性和可重用性,很容易把它做成一个函数:

 const closest = (array, goal) => array.reduce((prev, curr) => Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev); console.log(closest([20, 25, 30, 35, 5, 10, 15], 7)); console.log(closest([20, 25, 30, 35, 5, 10, 15], 8)); console.log(closest([1, 5, 7], -5)); console.log(closest([1, 5, 7], 4)); console.log(closest([1, 5, 7], 20));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM