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

假设我有这个号码列表:

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

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

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

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

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

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

 var l = new List() { 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 list = new List(){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 list = new List { 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 list = new List { 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 myList = new List() { 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 {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 numbers = new List() { 3, 5, 8, 11, 12, 13, 14, 21 }; List output = (from n in numbers where n > 13 // or whatever orderby n ascending //or descending select n).ToList();