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();
- Enumerable.Cast 扩展方法无法从int转换为long,为什么?
- .Net Core 2.0 Process.Start抛出“指定的可执行文件不是此OS平台的有效应用程序”
- 如何在c#中格式化1700到1’700和1000000到1’000’000?
- 允许迭代而不产生任何垃圾
- ASMX webservice不返回JSON,只能使用application / x-www-form-urlencoded contentType进行POST
- 我可以使用lambda语法忽略委托参数吗?
- C#上的边缘检测
- 像MS Paint一样调整位图大小 – 没有抗锯齿
- 在鼠标hover上设置状态栏文本 – 适用于控件但不适用于MenuItems