Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to find the closest number that is greater / less than an input

Tags:

c#

linq

Suppose I have this number list:

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

Suppose that I want to get the closest number that is less than 11, it would be 8 Suppose that I want to get the closest number that is greater than 13 that would be 14.

The numbers in list can't be duplicated and are always ordered. How can I write Linq for this?

like image 841
Sarawut Positwinyu Avatar asked Jun 22 '11 07:06

Sarawut Positwinyu


People also ask

How do I find the nearest number in C#?

var nearest = array. MinBy(x => Math. Abs((long) x - targetNumber));

What is any () in Linq?

The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.

How do I find the next record in Linq?

First(); var next = items . OrderBy(item => item.Id) . First(item => item.Id > currentId); var next = items .

How do you find the closest value to zero from an array with positive and negative numbers in Java?

String res = ""; Arrays. sort(arr); int num = arr[0]; int ClosestValue = 0; for (int i = 0; i < arr. length; i++) { //for negatives if (arr[i] < ClosestValue && arr[i] > num) num = arr[i]; //for positives if (arr[i] > ClosestValue && num < ClosestValue) num = arr[i]; } res = num; System.


2 Answers

with Linq assuming that the list is ordered I would do it like this:

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();

EDIT:

As I have received negative feedback about this answer and for the sake of people that may see this answer and while it's accepted don't go further, I explored the other comments regarding BinarySearch and decided to add the second option in here (with some minor change).

This is the not sufficient way presented somewhere else:

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

Now the code above doesn't cope with the fact that the value 10 might actually be in the list (in which case one shouldn't invert the index)! so the good way is to do it:

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];

I simply want to note that:

l.BinarySearch(11) == 3
//and
l.BinarySearch(10) == -4;
like image 88
ub1k Avatar answered Oct 15 '22 08:10

ub1k


Use Array.BinarySearch - no need for LINQ or visiting on average half the elements to find your target.

There are also a variety of SortedXXX classes that may be suitable for what you're doing [that will have such efficient O(log N) searches built-in]

like image 42
Ruben Bartelink Avatar answered Oct 15 '22 08:10

Ruben Bartelink