views:

343

answers:

3

I need a linq expression that will find the nearest numbers (both "greater or equal" and "less or equal") in an array for a given number.

E.g. Array - 1, 33, 66, 100

If I have the number 10, I want to return 1 and 33. If I have the number 70, I want to return 66 and 100. If I have the number 33, I want to return 33 and 66.

I could do this with some kind of basic for loop, but this is an operation on numbers in a database, so I'd prefer a linq to sql expression.

Edit: I was actually searching for a single linq expression to achieve this, but perhaps I was being a little hopeful :)

+1  A: 
var list = new[] { 1, 33, 66, 100 };

var n = 33;

var high = list
    .OrderBy(i=>i)
    .FirstOrDefault(i => i >= n);

var low = list
    .OrderByDescending(i => i)
    .FirstOrDefault(i => i <= n);

Console.WriteLine(low);
Console.WriteLine(high);

results in 1, 33

the only issue is that if you specify 33 for n, you will get 33, 33. Is this correct? Can both be the same number? If not, you will have to limit your select to possibly "<=" and then just ">".

You should be able to adapt the solution to Linq to SQL.

Andrew Robinson
A: 
        ArrayList arrList = new ArrayList();
        int number = 10;

        arrList.Add(1);
        arrList.Add(10);
        arrList.Add(20);
        arrList.Add(-12);

        int numberBelow = (from int i in arrList
                           where i <= number
                           select i).Max();

        int numberAbove = (from int i in arrList
                           where i >= number
                           select i).Min();

The number below is the maximum value less than your search value and likewise the number above is the minimum value greater than your search value. The only question is do you want greater than or equal or just greater than.

Dave Barker
+3  A: 

Similar to Andrews answer, but I prefer doing the filter before the OrderBy, which reduces the amount of data the query has to run through. Also OrderBy.First is the same as Min, and OrderByDescending.First is the same as Max.

var high = list
    .Where(i => i > n)
    .DefaultIfEmpty()
    .Min();

var low = list
    .Where(i => i <= n)
    .DefaultIfEmpty()
    .Max();
Cameron MacFarland
In the end, this runs on SQL. How does that affect the ordering and order of operations? It would be a good test but guessing in the end, they will be the same?
Andrew Robinson