5

How to get the list index where you can find the closest number?

List<int> list = new List<int> { 2, 5, 7, 10 };
int number = 9;

int closest = list.Aggregate((x,y) => 
Math.Abs(x-number) < Math.Abs(y-number) ? x : y);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
andres
  • 115
  • 1
  • 3
  • 8
  • 2
    andres, i take it you just want to expand on this question: http://stackoverflow.com/questions/5953552/how-to-get-the-closest-number-from-a-listint-with-linq.. which definitely means it could be homework :) – jim tollan May 10 '11 at 22:06
  • Exact duplicate: [How to get the closest number from a List with LINQ?](http://stackoverflow.com/questions/5953552/how-to-get-the-closest-number-from-a-listint-with-linq) - using the exact same example! And posted on the same date. – Peter Mortensen Jun 10 '11 at 07:00

5 Answers5

5

If you want the index of the closest number this will do the trick:

int index = list.IndexOf(closest);
goalie7960
  • 863
  • 7
  • 26
  • He wants to find the closest number "within" the list...e.g. the list value that is closest... – davidsleeps May 10 '11 at 22:09
  • @davidsleeps: I'm not sure that he does want to do that. I think this answer might actually be correct. The original question he got the code from is http://stackoverflow.com/questions/5953552/how-to-get-the-closest-number-from-a-listint-with-linq. The wording in the question, "number field" might refer to index. – Sani Huttunen May 10 '11 at 22:15
  • @Sani, i'm confused, but will leave it at that! – davidsleeps May 10 '11 at 23:40
3

You can include the index of each item in an anonymous class and pass it through to the aggregate function, and be available at the end of the query:

var closest = list
    .Select( (x, index) => new {Item = x, Index = index}) // Save the item index and item in an anonymous class
    .Aggregate((x,y) => Math.Abs(x.Item-number) < Math.Abs(y.Item-number) ? x : y);

var index = closest.Index;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Pop Catalin
  • 61,751
  • 23
  • 87
  • 115
1

Just enumerate over indices and select the index with the smallest delta as you would if you did a regular loop.

const int value = 9;
var list = new List<int> { 2, 5, 7, 10 };
var minIndex = Enumerable.Range(1, list.Count - 1)
    .Aggregate(0, (seed, index) =>
        Math.Abs(list[index] - value) < Math.Abs(list[seed] - value)
            ? index
            : seed);
Jeff Mercado
  • 129,526
  • 32
  • 251
  • 272
-1

Very minor changes to what you already have, since you seem to have the answer already:

        List<int> list = new List<int> { 2, 5, 7, 10 }; int number = 9;

        int closest = list.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y);
David
  • 1,743
  • 1
  • 18
  • 25
  • 1
    i'm going blind. other than formatting, where's the main diff??. i know there must be one -just can't figure it :) – jim tollan May 10 '11 at 22:10
-1

The closest number is the one where the difference is the smallest:

int closest = list.OrderBy(n => Math.Abs(number - n)).First();
Guffa
  • 687,336
  • 108
  • 737
  • 1,005