Lambda / LINQ выбрать минимум


Я пишу функцию, используя класс .NET GeoCoordinate. У нас есть класс Airport и класс City, Каждый из которых определяет свой собственный класс GeoCoordinate.

Мне нужно выбрать ближайший аэропорт относительно города, и я пытаюсь сделать это с помощью метода GetDistanceTo().

То, что у меня сейчас есть, выглядит примерно так:

Airport a = Airports.GetAllActiveAirports().Min(this.Coordinates.GetDistanceTo(n.Profile.Coordinates));

Другая (рабочая) функция, которая извлекает список ближайших аэропортов по расстоянию, использует:

List<Airports> airports = Airports.GetAllActiveAirports();
var nearby = 
    from a in airports
    where this.Coordinates.GetDistanceTo(a.Profile.Coordinates) > d
    select a;
foreach(Airport a in nearby)
{ 
    airports.Remove(a); 
}

Я видел примеры того, как это делается в одном линия с LINQ & lambdas, но я не совсем уверен, как выполнить это...есть указания?

3 5

3 ответа:

Если я получу ваш вопрос, эта линия получит минимальное расстояние от координат до активного аэропорта.

Airports.GetAllActiveAirports().Min(_ => Coordinates.GetDistanceTo(_.Profile.Coordinates))

Если вам нужен аэропорт, о котором идет речь, то:

var airports = Airports.GetAllActiveAirports();
var closest = airports.First(_ => Coordinates.GetDistanceTo(_.Profile.Coordinates) == airports.Min(_ => Coordinates.GetDistanceTo(_.Profile.Coordinates)))

Вам не нужно держать его в одной строке... Visual Studio не будет исчерпывать пространство.

Еще лучшим вариантом, не получая минимума в каждой итерации, было бы:

var airports = Airports.GetAllActiveAirports();
var minDistance = airports.Min(_ => Coordinates.GetDistanceTo(_.Profile.Coordinates))
var closest = airports.First(_ => Coordinates.GetDistanceTo(_.Profile.Coordinates) == minDistance)

Принятый ответ вызывает 2 вызова в GetDistance для каждого аэропорта. Вот как вы можете сделать это за один проход:

var closestAirport = Airports.GetAllActiveAirports()
    .Select(x => new {
        Airport = x, 
        Distance = this.Coordinates.GetDistanceTo(x.Profile.Coordinates)})
    .Aggregate((a1, a2) => a1.Distance < a2.Distance ? a1 : a2)
    .Airport;

Min бросит InvalidOperationException, если нет значений. Вы можете попробовать что-то вроде этого. Если ничего не найдено, то ближайшим будет null:

var closest = Airports.GetAllActiveAirports().OrderBy(x => x.GetDistanceTo(n.Profile.Coordinates)).FirstOrDefault();