LINQ查找比输入大/小的最接近的数字

本文关键字:最接近 数字 查找 输入 LINQ | 更新日期: 2023-09-27 18:00:03

假设我有这个数字列表:

List<int> = new List<int>(){3,5,8,11,12,13,14,21}

假设我想得到小于11的最接近的数字,它将是8假设我想得到一个最接近的大于13的数字,那就是14。

列表中的数字不能重复,并且总是按顺序排列的。我该怎么写林克?

LINQ查找比输入大/小的最接近的数字

如果Linq假设列表是有序的,我会这样做:

var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var lessThan11 = l.TakeWhile(p => p < 11).Last();
var greaterThan13 = l.SkipWhile(p => p <= 13).First();

编辑:

由于我收到了关于这个答案的负面反馈,为了那些可能看到这个答案的人,虽然它被接受了,但不要走得更远,我探索了关于BinarySearch的其他评论,并决定在这里添加第二个选项(有一些小的更改)。

这在其他地方是不够的:

var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = ~l.BinarySearch(10) -1;
var value = l[indexLessThan11];

现在,上面的代码无法处理值10实际上可能在列表中的事实(在这种情况下,不应该反转索引)!所以最好的方法是:

var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = l.BinarySearch(10);
if (indexLessThan11 < 0) // the value 10 wasn't found
{    
    indexLessThan11 = ~indexLessThan11;
    indexLessThan11 -= 1;
}
var value = l[indexLessThan11];

我只想指出:

l.BinarySearch(11) == 3
//and
l.BinarySearch(10) == -4;

使用Array.BinarySearch-无需LINQ或访问平均一半的元素即可找到目标。

还有各种SortedXXX类可能适合您正在做的事情[内置高效的O(log N)搜索]

您可以使用二进制搜索来完成此操作。如果你搜索11,那么很明显你会得到你想要的索引。如果你搜索10并使用结果的逐位补码,你会得到最接近的匹配。

   List<int> list = new List<int>(){3,5,8,11,12,13,14,21};
   list.Sort();
   int index = list.BinarySearch(10);
   int found =  (~index)-1;
   Console.WriteLine (list[found]); // Outputs 8

在的另一个方向上搜索也是如此

int index = list.BinarySearch(15);
Console.WriteLine("Closest match : " + list[+~index]); // Outputs 21

二进制搜索也非常快。

11以下最接近的数字:

        int someNumber = 11;
        List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
        var intermediate = from i in list
                     where i < someNumber
                     orderby i descending
                     select i;
        var result = intermediate.FirstOrDefault();

13以上最接近的数字:

        int someNumber = 13;
        List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
        var intermediate = from i in list
                     where i > someNumber
                     orderby i
                     select i;
        var result = intermediate.FirstOrDefault();

这是我的答案

List<int> myList = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
    int n = 11;
    int? smallerNumberCloseToInput = (from n1 in myList
                                    where n1 < n
                                    orderby n1 descending
                                    select n1).First();
    int? largerNumberCloseToInput = (from n1 in myList
                                    where n1 > n
                                    orderby n1 ascending
                                    select n1).First();
var list = new List<int> {14,2,13,11,5,8,21,12,3};
var tested = 11;
var closestGreater = list.OrderBy(n => n)
                         .FirstOrDefault(n => tested < n); // = 12
var closestLess = list.OrderByDescending(n => n)
                      .FirstOrDefault(n => tested > n); // = 8
if (closestGreater == 0)
    System.Diagnostics.Debug.WriteLine(
        string.Format("No number greater then {0} exists in the list", tested));
if (closestLess == 0)
    System.Diagnostics.Debug.WriteLine(
        string.Format("No number smaler then {0} exists in the list", tested));

这是我的方式,希望这能帮助到别人!

List<float> list = new List<float> { 4.0f, 5.0f, 6.0f, 10.0f, 4.5f,  4.0f, 5.0f, 6.0f, 10.0f, 4.5f, 4.0f, 5.0f, 6.0f, 10.0f };
float num = 4.7f;
float closestAbove = list.Aggregate((x , y) => (x < num ? y : y < num ? x : (Math.Abs(x - num)) < Math.Abs(y - num) ? x : y));
float closestBelow = list.Aggregate((x , y) => (x > num ? y : y > num ? x : (Math.Abs(x - num)) < Math.Abs(y - num) ? x : y));
Console.WriteLine(closestAbove);
Console.WriteLine(closestBelow);

这意味着你不必订购列表

来源:从这里添加:如何从列表中获得最接近的数字<int>与LINQ?

扩展代码

float closestAboveExplained = list.Aggregate((closestAbove , next) => {
    if(next < num){
        return closestAbove;
    }
    if(closestAbove < num){
        return next;
    }
    else{
        if(Math.Abs(closestAbove - num) < Math.Abs(next - num)){
            return closestAbove;
        }
    }
    return next;
});

您可以为此使用查询,例如:

List<int> numbers = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
List<int> output = (from n in numbers
                            where n > 13 // or whatever
                            orderby n ascending //or descending
                            select n).ToList();