在特定条件下使用LINQ从列表中获取号码

时间:2018-09-28 09:24:44

标签: c# linq math

我有一个数字列表,我想获得比通过的数字还要多的下一个>=数字,但是当我传递的值大于列表中的最大数字时,就会出现问题。例如,当我通过41并且列表中最大的数字是40时,它将不起作用,因此我希望它返回40。

var numbers = new[] {30, 20, 40};

我希望它像这样工作:

numbers.GetNearest(45) -> 40
numbers.GetNearest(40) -> 40
numbers.GetNearest(31) -> 40
numbers.GetNearest(30) -> 30
numbers.GetNearest(29) -> 30
numbers.GetNearest(1) -> 20

单独使用LINQ可能吗,还是有众所周知的算法?

我现在拥有的是这样的:

numbers.OrderBy(n => n).FirstOrDefault(n => n >= minute)

但是当我传递的值大于40时它不起作用

我不想要最接近的数字,但是比我通过的数字还要下一个>=,但是对于某些大于列表中最大数字的数字将不起作用,因此我只想返回最后一个。

4 个答案:

答案 0 :(得分:5)

DefaultIfEmpty()定义特殊情况

var numbers = new[] { 30, 20, 40 };
Array.Sort(numbers);
int result = numbers.Where(n => n >= minute).DefaultIfEmpty(numbers.Last()).First();

测试用例:https://dotnetfiddle.net/nIEsRO

答案 1 :(得分:3)

更新

var numbers = new[]{30, 20, 40};
var number = 25;
var closest = numbers.OrderBy(n => n)
                     .Cast<int?>()
                     .FirstOrDefault(n => n >= number) ?? numbers.Last();
Console.WriteLine(closest);

注意 :由于default(int)可能是一种更好的方式,因此Cast仅处理0。

输出

30

Full Demo Here


原始

您可以按差异订购

var closest = numbers.OrderBy(x => Math.Abs((long)x - number))
                     .First();

答案 2 :(得分:1)

您没有提供有关特定条件的足够详细信息,因此我只能给您以下答案:

var numbers = new[] {30, 20, 40};

var ordered = numbers.Select(x => (int?)x).OrderBy(x => x);

int? value  = ordered.FirstOrDefault(x => x >= 41) ?? ordered.LastOrDefault();

答案 3 :(得分:0)

有人用Aggregate发布了答案,但不能完全按照我希望的方式工作,但删除了它。因此,我想出了使用Aggregate的自己的解决方案,我认为它应该比首先使用OrderBy更快。

numbers.Aggregate((x, y) =>
{
    var min = Math.Min(x, y);
    return number <= min ? min : Math.Max(x, y);
});

我花了一段时间才弄清楚,但它解决了我的问题。如果您发现其中有任何缺陷,请告诉我。