C # поиск ближайшего значения в массиве

int[] array = new int[5]{5,7,8,15,20}; int TargetNumber = 13; 

Для целевого номера я хочу найти ближайшее число в массиве. Например, когда целевое число равно 13, ближайший номер к нему в вышеприведенном массиве равен 15. Как это сделать программно в C #?

EDIT: скорректируйте запросы ниже, чтобы преобразовать их в long арифметику, чтобы избежать проблем с переполнением.

Я бы, вероятно, использовал метод MinBy :

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

Или вы можете просто использовать:

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

… но это сортирует всю коллекцию, которую вам действительно не нужно. Понятно, что это не будет иметь большого значения для небольшого массива … но это просто не совсем правильно, по сравнению с описанием того, что вы на самом деле пытаетесь сделать: найти элемент с минимальным значением в соответствии с некоторой функцией.

Обратите внимание, что оба из них не сработают, если массив пуст, поэтому сначала проверьте его.

Если вы используете .Net 3.5 или выше, LINQ может помочь вам здесь:

 var closest = array.OrderBy(v => Math.Abs((long)v - targetNumber)).First(); 

Кроме того, вы можете написать свой собственный метод расширения:

 public static int ClosestTo(this IEnumerable collection, int target) { // NB Method will return int.MaxValue for a sequence containing no elements. // Apply any defensive coding here as necessary. var closest = int.MaxValue; var minDifference = int.MaxValue; foreach (var element in collection) { var difference = Math.Abs((long)element - target); if (minDifference > difference) { minDifference = (int)difference; closest = element; } } return closest; } 

Полезно:

 var closest = array.ClosestTo(targetNumber); 

И Джон, и Рич дали отличные ответы с MinBy и ClosestTo . Но я бы никогда не рекомендовал использовать OrderBy если вы намерены найти один элемент. Это слишком неэффективно для таких задач. Это просто неправильный инструмент для работы.

Вот техника, которая работает чуть лучше MinBy, уже включена в .NET framework, но менее элегантна, чем MinBy: Aggregate

 var nearest = array.Aggregate((current, next) => Math.Abs((long)current - targetNumber) < Math.Abs((long)next - targetNumber) ? current : next); 

Как я уже сказал, не такой элегантный, как метод Джона, но жизнеспособный.

Производительность на моем компьютере:

  1. Для (каждого) Loops = fastest
  2. Агрегат = 2.5x медленнее, чем циклы
  3. MinBy = 3,5x медленнее циклов
  4. OrderBy = 12x медленнее, чем циклы

Я нашел этот очень сексуальный подход несколько лет назад в Math.NET Numerics https://numerics.mathdotnet.com/, который работает с BinarySearch в массиве. Это была хорошая помощь в подготовке к интерполяции и работает до .Net 2.0:

 public static int LeftSegmentIndex(double[] array, double t) { int index = Array.BinarySearch(array, t); if (index < 0) { index = ~index - 1; } return Math.Min(Math.Max(index, 0), array.Length - 2); } 

Эффективный пользовательский код будет более полезен.

 public static int FindNearest(int targetNumber, IEnumerable collection) { var results = collection.ToArray(); int nearestValue; if (results.Any(ab => ab == targetNumber)) nearestValue = results.FirstOrDefault(i => i == targetNumber); else{ int greaterThanTarget = 0; int lessThanTarget = 0; if (results.Any(ab => ab > targetNumber)) { greaterThanTarget = results.Where(i => i > targetNumber).Min(); } if (results.Any(ab => ab < targetNumber)) { lessThanTarget = results.Where(i => i < targetNumber).Max(); } if (lessThanTarget == 0) { nearestValue = greaterThanTarget; } else if (greaterThanTarget == 0) { nearestValue = lessThanTarget; } else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber) { nearestValue = lessThanTarget; } else { nearestValue = greaterThanTarget; } } return nearestValue; } 
  • Измерение петли по размеру массива в plpgsql
  • Массив сортировки Javascript по двум полям
  • Манипулировать multidimensional array в функции
  • как разобрать JSONArray в android
  • Является ли массив примитивов Java хранимым в стеке или куче?
  • Как я могу сохранить результат команды find в виде массивов в Bash
  • JsonMappingException: из токена START_ARRAY
  • Перечислить дубликаты массивов со счетом
  • Сортировка многомерного массива в VBA
  • Каков самый элегантный способ проверить, истинны ли все значения в булевом массиве?
  • JSON Array итерация в Android / Java
  • Давайте будем гением компьютера.