2

I'm trying to round a result value to the next number in a list.

If the value is (187) I need to set the result to (240)

int[] list = new int[] { 16, 25, 35, 50, 70, 95, 120, 150, 185, 240, 300, 400 };
double max;
max = list.Where(x => x <= result).Max();

But this does not work.

AussieJoe
  • 1,285
  • 1
  • 14
  • 29
Mohamed Ahmed
  • 113
  • 11

5 Answers5

8

You're close:

list.Where(x => x >= result).Min();
D Stanley
  • 149,601
  • 11
  • 178
  • 240
4

You just want the first item greater than or equal to your expected result:

var max = list.FirstOrDefault(x => x >= result)

NOTE: This assumes the list is ordered, as your example seems to suggest.

If you want to get an exception if there's no match then just use First:

var max = list.First(x => x >= result)
Sean
  • 60,939
  • 11
  • 97
  • 136
  • 1
    That is assuming the list is ordered. I mean, it is, in the example. But nowhere stated explicitly. – RobIII Aug 21 '19 at 15:39
4

Try using List.BinarySearch.

Returns the zero-based index of item in the sorted List, if item is found; otherwise, a negative number that is the bitwise complement of the index of the next element that is larger than item or, if there is no larger element, the bitwise complement of Count.

var list = new List<int> { 16, 25, 35, 50, 70, 95, 120, 150, 185, 240, 300, 400 };

int index = list.BinarySearch(result);
int rounded;
if (index < 0)
{
    if (~index == list.Count)
    {
        throw new InvalidOperationException("Number is too big.");
    }
    rounded = list[~index];
}
else
{
    rounded = list[index];
}

The asymptotic complexity of this method is O(log n), where n is the length of the list, whereas the complexity of Where/First is O(n), which probably won't matter in your case, but is still good to know.

Gebb
  • 6,371
  • 3
  • 44
  • 56
0

If you want to round upwards, you can find which value in the list subtracted by your value is greater than or equal to 0.

max = list
    .OrderBy(x => x) // Can be skipped if list is ordered.
    .FirstOrDefault(x => x - value >= 0) // if "value" is 187, max will be 240.

Ensure you have something that handles if the "max" value is null.

Hope this helps.

The Don
  • 343
  • 2
  • 13
  • 1
    You are _also_ assuming the list is ordered. I mean, it is, in the example. But nowhere stated explicitly. Just a heads-up. – RobIII Aug 21 '19 at 15:43
  • @RobIII - Good catch! Made the necessary adjustment. But @D Stanley's answer is the simplest and the correct one. – The Don Aug 22 '19 at 16:04
0

If you want the closest value

var list = new List<int> { 16, 25, 35, 50, 70, 95, 120, 150, 185, 240, 300, 400 };
int value = 187;
var nearestValue = (from v in list
        let  d = Math.Abs(value - v)
        orderby d
        select v)
    .FirstOrDefault();
Vlad DX
  • 4,200
  • 19
  • 28
Tohm
  • 305
  • 1
  • 5
  • So for the value = 187 the closest value is 185 – Tohm Aug 21 '19 at 16:06
  • 1
    I suggest to update the query to solve the original task: 187 -> 240. `from v in list let d = v - value where d > 0 orderby d select v` – Vlad DX Aug 21 '19 at 16:10