LINQ, чтобы найти самое близкое число, которое больше/меньше входного
Предположим, что у меня есть список номеров:
List<int> = new List<int>(){3,5,8,11,12,13,14,21}
Предположим, что я хочу получить самое близкое число, которое меньше 11, это будет 8
Предположим, что я хочу получить самое близкое число, которое больше 13, что будет 14.
Цифры в списке не могут быть дублированы и всегда упорядочены. Как я могу написать Linq для этого?
Ответы
Ответ 1
с Linq, предполагая, что список упорядочен, я бы сделал это следующим образом:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var lessThan11 = l.TakeWhile(p => p < 11).Last();
var greaterThan13 = l.SkipWhile(p => p <= 13).First();
ИЗМЕНИТЬ:
Поскольку я получил отрицательные отзывы об этом ответе и ради людей, которые могут видеть этот ответ, и, хотя он принят, не идет дальше, я изучил другие комментарии относительно BinarySearch и решил добавить здесь второй вариант ( с некоторыми незначительными изменениями).
Это недостаточный способ, представленный где-то еще:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = ~l.BinarySearch(10) -1;
var value = l[indexLessThan11];
Теперь приведенный выше код не справляется с тем, что значение 10
действительно может быть в списке (в этом случае нельзя инвертировать индекс)! поэтому хороший способ это сделать:
var l = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
var indexLessThan11 = l.BinarySearch(10);
if (indexLessThan11 < 0) // the value 10 wasn't found
{
indexLessThan11 = ~indexLessThan11;
indexLessThan11 -= 1;
}
var value = l[indexLessThan11];
Я просто хочу отметить, что:
l.BinarySearch(11) == 3
//and
l.BinarySearch(10) == -4;
Ответ 2
Использовать Array.BinarySearch
- нет необходимости в LINQ или посещать в среднем половину элементов для поиска вашей цели.
Существует также множество классов SortedXXX
, которые могут быть подходящими для того, что вы делаете [у которого будет такой эффективный поиск O (log N)]
Ответ 3
Вы можете сделать это, используя двоичный поиск. Если вы ищете 11, то, очевидно, вы получите индекс после. Если вы ищете 10 и используете побитовое дополнение к результату, вы получите самое близкое соответствие.
List<int> list = new List<int>(){3,5,8,11,12,13,14,21};
list.Sort();
int index = list.BinarySearch(10);
int found = (~index)-1;
Console.WriteLine (list[found]); // Outputs 8
То же самое происходит в другом направлении
int index = list.BinarySearch(15);
Console.WriteLine("Closest match : " + list[+~index]); // Outputs 21
Бинарные поиски также очень быстрые.
Ответ 4
ближайший номер ниже 11:
int someNumber = 11;
List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
var intermediate = from i in list
where i < someNumber
orderby i descending
select i;
var result = intermediate.FirstOrDefault();
ближайший номер выше 13:
int someNumber = 13;
List<int> list = new List<int> { 3, 5, 8, 11, 12, 13, 14, 21 };
var intermediate = from i in list
where i > someNumber
orderby i
select i;
var result = intermediate.FirstOrDefault();
Ответ 5
Это мой ответ
List<int> myList = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
int n = 11;
int? smallerNumberCloseToInput = (from n1 in myList
where n1 < n
orderby n1 descending
select n1).First();
int? largerNumberCloseToInput = (from n1 in myList
where n1 > n
orderby n1 ascending
select n1).First();
Ответ 6
Вы можете использовать запрос для этого, например:
List<int> numbers = new List<int>() { 3, 5, 8, 11, 12, 13, 14, 21 };
List<int> output = (from n in numbers
where n > 13 // or whatever
orderby n ascending //or descending
select n).ToList();
Ответ 7
var list = new List<int> {14,2,13,11,5,8,21,12,3};
var tested = 11;
var closestGreater = list.OrderBy(n => n)
.FirstOrDefault(n => tested < n); // = 12
var closestLess = list.OrderByDescending(n => n)
.FirstOrDefault(n => tested > n); // = 8
if (closestGreater == 0)
System.Diagnostics.Debug.WriteLine(
string.Format("No number greater then {0} exists in the list", tested));
if (closestLess == 0)
System.Diagnostics.Debug.WriteLine(
string.Format("No number smaler then {0} exists in the list", tested));