Stavros
Stavros

Reputation: 147

Find next highest and next lowest number in list c#

I have a list of numbers and if the number that I am looking for is not in the list I want to be able to find the next value that is in the list above and below the number that I have asked for.

double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
//do code to find next highest/lowest
double higher = 7;
double lower = 3;

for example, because 5 is not exactly in the list itself I want it to return the next item that is closest to 5 both above and below. so for this case, 3 and 7.

Upvotes: 2

Views: 4049

Answers (6)

maccettura
maccettura

Reputation: 10818

Original version

You can use List's Sort() method, then use LINQ FirstOrDefault() and LastOrDefault()

List<double> numbers = new List<double>()
{
    1, 2, 3, 7, 8, 9
};

double input = 5;
    
numbers.Sort();

double nextHighest = numbers.FirstOrDefault(x => x > input);
double nextLowest = numbers.LastOrDefault(x => x < input);

Better version edit This wont actually work for both cases

Originally I suggested this as a more efficient solution, but this will not work for the number before a given input. It only works for finding a number after the given input.

You can be more efficient since you are using List<T>, there is a Find() method that accepts a predicate:

List<double> numbers = new List<double>()
{
    1, 2, 3, 7, 8, 9
};

double input = 5;
    
numbers.Sort();

double nextHighest = numbers.Find(x => x > input);

This will exit the loop immediately upon finding a match (whereas LastOrDefault() has to iterate the entire collection)

Fiddle for both here

Upvotes: 7

Nathan Adduci
Nathan Adduci

Reputation: 21

The other answer given is not very good if you are going to be using a large list of values, because it needs to index the list twice.

If you make your own loop like this:

double higher = Double::MaxValue;
double lower = Double::MinValue;

double index = 5; // the value you want to get.
List<double> list = {1,2,3,7,8,9}; // the list you're searching.

for(int i = 0; i < list.Count; i++) 
{
    if(list[i] > index && list[i] < higher)
        higher = list[i]; // sets the higher value.
    else if(list[i] < index && list[i] > lower)
        lower = list[i]; // sets the lower value.
}

After execution, this would give you 3 and 7, the correct values.

I should note that this takes O(n) time, because it only loops once. This will be faster than anything posted at the time of this edit (plus it's pretty easy to see what its doing).

Upvotes: 0

Nguyen Thanh Binh
Nguyen Thanh Binh

Reputation: 128

You can archieve that by this way. These codes below was tested from my side.

    double index = 5;
    double higher = 0 ;
    double lower = 0;

    List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
    list.Sort();//Sort list from low to high numbers

    if(!list.Contains(index))
    {
      foreach (var item in list)
      {
         if(item < index)
         {
            lower = item;                      
         }
         if (item > index)
         {
             higher = item;  
             break;  
         }
       }
     }
Console.WriteLine(index);//5
Console.WriteLine(lower);//3
Console.WriteLine(higher);//7

Upvotes: -1

Daniele Sartori
Daniele Sartori

Reputation: 1703

In case you want all the occurency

double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };
for(int i =1 ; i <= 9-5 ; i++)
{
    List<double> NextHigh = list.Where(x=> x-i == index).ToList();
    if(! (NextHigh.Count == 0))
    {
        NextHigh.Dump();
        break;
    }
}

for(int i =1 ; i <= 5-1 ; i++)
{
    List<double> NextLow = list.Where(x=> x+i == index).ToList();
    if( !(NextLow.Count== 0))
    {
        NextLow.Dump();
        break;
    }
}

Upvotes: 0

Ole Albers
Ole Albers

Reputation: 9285

LinQ-Solution:

double index = 5;
List<double> list = new List<double>() { 1, 2, 3, 7, 8, 9, };

double higher=list.OrderBy(q=>q).First(q=>q>index); // 7
double lower=list.OrderByDescending(q=>q).First(q=>q<index); // 3

Explanation: First you sort the list Ascending or Descending. After that all you have to do is to find the greater or smaller number;

You might want to replace First() by FirstOrDefault() if you do not want an exception if no higher/lower value exists.

Upvotes: 0

Cosmin Ioniță
Cosmin Ioniță

Reputation: 4045

One solution would be sort the list and then iterate over it to find the spot where list[i] < index < list[i+1]. This would take O(n * log(n)) time.

A better solution is simply iterate over the list and use 2 variables that you will update accordingly (let's say max and min).

max will store the maximum value that is below the index.

min will store the minimum value that is above the index.

That last solution takes O(n) time.

Upvotes: 0

Related Questions