Как получить ближайший номер из списка с помощью LINQ?

#c# #linq #list #numbers

#c# #linq #Список #числа

Вопрос:

Как получить ближайший номер из List<int> с помощью LINQ?

Например:

 List<int> numbers = new List<int>();
numbers.Add(2);
numbers.Add(5);
numbers.Add(7);
numbers.Add(10)
  

Мне нужно найти ближайшее значение в списке к номеру 9. В данном случае 10.

Как я могу это сделать с помощью LINQ?

Комментарии:

1. Не могли бы вы, пожалуйста, пояснить, что вы подразумеваете под «ближе к списку»?

2. Какие числа, какой список и что вы пробовали?

3. Любой код, который вы могли бы предоставить, всегда помогает понять ваш вопрос и, таким образом, ответить на него. 🙂

4. Известно ли, что список находится в порядке? Содержит ли список дубликаты? Что должно произойти, если более одного числа являются «ближайшими»? Насколько большим, вероятно, будет список?

5. Последний упомянутый случай исключительно интересен. Ни один из предоставленных ответов, похоже, не поддается легкому преобразованию в «стабильный» в том смысле, что большее или меньшее число возвращается последовательно.

Ответ №1:

Если вы используете LINQ для объектов, а список длинный, я бы использовал:

 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);
  

Этот метод немного сложнее, чем решение, предложенное Энтони Пеграмом, но его преимущество в том, что вам не нужно сначала сортировать список. Это означает, что у вас есть временная сложность O(n) вместо O(n*log(n)) и использование памяти O(1) вместо O(n) .

Комментарии:

1. спасибо за ответ, итак, я не понимаю эту часть: ? x: y, что это значит?

2. Это оператор условия. Смотрите msdn.microsoft.com/en-us/library/ty67wk28.aspx . Я использую его для выбора x или y , в зависимости от того, какой из них ближе всего к number .

3. как также узнать об индексе? индекс номера шкафа??

Ответ №2:

Если вы хотите использовать LINQ для выполнения этой задачи, вы можете сделать это, как показано ниже.

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

// find closest to number
int closest = list.OrderBy(item => Math.Abs(number - item)).First();
  

Комментарии:

1. Недостатком этого решения является то, что сначала приходится упорядочивать список, что снижает производительность, если список длинный. Смотрите мой ответ для решения, которое возвращает значение через O(n) время.

2. @Элиан, я согласен. Мой, возможно, более удобочитаемый. Я бы высказался за общий цикл, чтобы полностью избежать LINQ, если производительность была недостаточно хорошей, но у меня есть своя работа. 😉

3. Я бы предпочел использовать LINQ вместо методов расширения. Тем не менее, это все еще красивый код. Никакой преждевременной оптимизации, просто простой чистый код. за это.

Ответ №3:

Все решения, приведенные выше, в лучшем случае являются O(N) .

Если у вас большой список и вы выполняете этот запрос к ближайшему элементу несколько раз, было бы эффективнее сначала отсортировать список ( O(NlogN) ), а затем использовать List<T>.BinarySearch для каждого запроса. Производительность для k запросов O( (k N)logN ) выше, по сравнению с O(kN) предыдущим методом.

Ответ №4:

В наши дни также существует приятный и простой вариант:

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

int min = list.Min(i => (Math.Abs(number - i), i)).i;
  

Ответ №5:

Не могли бы вы выполнить бинарный поиск. Это встроенный метод в c #, который поможет вам выполнить поиск ближайшего номера. Вот пример:https://msdn.microsoft.com/en-us/library/y15ef976 (v =против110).aspx

Комментарии:

1. Двоичный поиск требует, чтобы список был отсортирован первым, и это может снизить производительность.

Ответ №6:

Используйте это, чтобы получить ближайшее меньшее или большее значение в зависимости от используемого вами условия.

  List<int> list = new List<int> { 2, 5, 7, 10 };
 int number = 9;
 var closest = list.Where(numbers => numbers > number).First();
 Console.WriteLine(closest);
 Console.ReadLine();
  

Комментарии:

1. Это возвращает неверный результат, если совпадение не ниже искомого номера. В примере, если вы выполните поиск по 8, будет возвращено 10.