Как выполнить.Max () на свойстве всех объектов в наборе и возвратить объект с максимальным значением [дубликат]

261
задан Uwe Keim 6 August 2019 в 06:07
поделиться

4 ответа

У нас есть метод расширения , чтобы сделать это в MoreLINQ . Вы можете посмотреть на реализацию там, но в основном это случай перебора данных, запоминания максимального элемента, который мы видели до сих пор, и максимального значения, полученного им в рамках проекции.

В вашем случае вы бы что-то сделали например:

var item = items.MaxBy(x => x.Height);

Это лучше (IMO), чем любое из представленных здесь решений, кроме второго решения Мердада (которое в основном совпадает с MaxBy ):

  • Это O (n) в отличие от предыдущий принятый ответ , который находит максимальное значение на каждой итерации (что делает его O (n ^ 2))
  • Решение для упорядочивания: O (n log n)
  • Принимая Max значение, а затем найти первый элемент с этим значением O (n), но повторяет последовательность дважды. По возможности следует использовать LINQ в однопроходном режиме.
  • Его намного проще читать и понимать, чем агрегированную версию, и он оценивает проекцию только один раз для каждого элемента
263
ответ дан 23 November 2019 в 02:35
поделиться

Это потребует сортировки (O (n log n)), но это очень просто и гибко. Еще одно преимущество - возможность использовать его с LINQ to SQL:

var maxObject = list.OrderByDescending(item => item.Height).First();

Обратите внимание, что это дает преимущество перечисления последовательности list только один раз. Хотя это может не иметь значения, если list является List , который за это время не меняется, это может иметь значение для произвольных объектов IEnumerable . Ничто не гарантирует, что последовательность не изменится в разных перечислениях, поэтому методы, которые делают это несколько раз, могут быть опасными (и неэффективными, в зависимости от характера последовательности). Тем не менее, это все еще далеко не идеальное решение для больших последовательностей. Я предлагаю написать собственное расширение MaxObject вручную, если у вас есть большой набор элементов, чтобы можно было сделать это за один проход без сортировки и прочего (O (n)):

static class EnumerableExtensions {
    public static T MaxObject<T,U>(this IEnumerable<T> source, Func<T,U> selector)
      where U : IComparable<U> {
       if (source == null) throw new ArgumentNullException("source");
       bool first = true;
       T maxObj = default(T);
       U maxKey = default(U);
       foreach (var item in source) {
           if (first) {
                maxObj = item;
                maxKey = selector(maxObj);
                first = false;
           } else {
                U currentKey = selector(item);
                if (currentKey.CompareTo(maxKey) > 0) {
                    maxKey = currentKey;
                    maxObj = item;
                }
           }
       }
       if (first) throw new InvalidOperationException("Sequence is empty.");
       return maxObj;
    }
}

и используйте его с:

var maxObject = list.MaxObject(item => item.Height);
192
ответ дан 23 November 2019 в 02:35
поделиться

Выполнение заказа с последующим выбором первого элемента - это напрасная трата времени на размещение элементов после первого. Вам не важен их порядок.

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

var maxHeight = dimensions
    .Aggregate((agg, next) => 
        next.Height > agg.Height ? next : agg);

var maxHeightAndWidth = dimensions
    .Aggregate((agg, next) => 
        next.Height >= agg.Height && next.Width >= agg.Width ? next: agg);
135
ответ дан 23 November 2019 в 02:35
поделиться

Я считаю, что сортировка по столбцу, для которого вы хотите получить максимальное значение, а затем захват первого, должна работать. Однако, если имеется несколько объектов с одинаковым значением MAX, будет захвачен только один:

private void Test()
{
    test v1 = new test();
    v1.Id = 12;

    test v2 = new test();
    v2.Id = 12;

    test v3 = new test();
    v3.Id = 12;

    List<test> arr = new List<test>();
    arr.Add(v1);
    arr.Add(v2);
    arr.Add(v3);

    test max = arr.OrderByDescending(t => t.Id).First();
}

class test
{
    public int Id { get; set; }
}
3
ответ дан 23 November 2019 в 02:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: