LINQ找到大于/小于输入的最接近的数字

Sar*_*nyu 10 c# linq

假设我有这个号码列表:

List<int> = new List<int>(){3,5,8,11,12,13,14,21}
Run Code Online (Sandbox Code Playgroud)

假设我想得到最接近的数字,小于11,那就是8假设我想得到最接近的数字,大于13,即14.

列表中的数字不能重复,并且始终是有序的.我怎么能为此写Linq?

ub1*_*b1k 17

与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();
Run Code Online (Sandbox Code Playgroud)

编辑:

由于我收到了关于这个答案的负面反馈,并且为了那些可能看到这个答案的人,并且虽然它被接受了但是没有进一步,我探讨了关于BinarySearch的其他评论,并决定在这里添加第二个选项(有一些未成年人)更改).

这是在其他地方提出的不充分的方式:

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

现在上面的代码不能处理这个值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];
Run Code Online (Sandbox Code Playgroud)

我只想注意:

l.BinarySearch(11) == 3
//and
l.BinarySearch(10) == -4;
Run Code Online (Sandbox Code Playgroud)


Rub*_*ink 11

使用Array.BinarySearch- 不需要LINQ或平均访问一半元素来查找目标.

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


yas*_*891 5

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();
Run Code Online (Sandbox Code Playgroud)

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();
Run Code Online (Sandbox Code Playgroud)


Vin*_*cio 5

您可以使用二进制搜索来执行此操作.如果你搜索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
Run Code Online (Sandbox Code Playgroud)

同样在另一个方向搜索

int index = list.BinarySearch(15);

Console.WriteLine("Closest match : " + list[+~index]); // Outputs 21
Run Code Online (Sandbox Code Playgroud)

二进制搜索也非常快.