There is an array of objects of class A

 class A { pubic double value; } 

How to use LINQ to find an element with the minimum value value, and not the value itself, as would happen in the case of arr.Min(a => a.value) ?

5 answers 5

Did not meet a construction which would execute this action for one Linq request. And for two to do is quite simple:

 double min = arr.Min(a => a.value); var result = arr.FirstOrDefault(a => a.Value == min); 

Option 2: Implement the IComparable<T> interface in your class:

 class A : IComparable<A> { public double value; public int CompareTo(A other) { return value.CompareTo(other.value); } } 

Then the Min() method can be called like this, and it returns an object of class A with the minimum value of the value field:

 var result = arr.Min(); 
  • Generally Aggregate :) - Qwertiy

With Linq, this is possible, but inefficient. A simpler solution would be to write the appropriate method; for example:

 public static TItem MinByKey<TItem, TKey>( this IEnumerable<TItem> items, Func<TItem, TKey> keySelector) { var comparer = Comparer<TKey>.Default; var enumerator = items.GetEnumerator(); if (!enumerator.MoveNext()) throw new InvalidOperationException("Collection is empty."); TItem minItem = enumerator.Current; TKey minKey = keySelector(minItem); while (enumerator.MoveNext()) { TKey key = keySelector(enumerator.Current); if (comparer.Compare(key, minKey) < 0) { minItem = enumerator.Current; minKey = key; } } return minItem; } 

Then the task will be reduced to a challenge.

 arr.MinByKey(a => a.value); 
  • Why not effective? - Anatol
  • one
    @Anatol Alternative options are: 1. Search for a minimum, then search for the index of this item - two passes through the collection. 2. Converting elements into tuples (элемент, индекс) , then finding the minimum and extracting the index from the tuple is one pass, but you need to create tuples. If the type of the tuple is significant (Value type), then this option, in principle, is optimal, otherwise there will be an additional memory allocation. - AlexeyM
 var a = array.Aggregate((r, x) => r.Value < x.Value ? r : x); 

Complete code: https://ideone.com/80oSKs

 using System; using System.Linq; class A { public double Value; public static implicit operator A(double x) { return new A() { Value = x }; } } public class Test { public static void Main() { var array = new A[] { 1.7, 2.3, -7.8, -11.1, 4.5, 42 }; var a = array.Aggregate((r, x) => r.Value < x.Value ? r : x); Console.WriteLine(a.Value); Console.WriteLine(Object.ReferenceEquals(a, array[3])); } } 

Result:

 -11.1 True 
     a.OrderBy(e => e.value).First(); 

    In one short request, but it is not efficient.

    • You can do better, although longer) :) - Qwertiy

    Since we raised this question: the simplest method is not to build your own bicycle, but to use a ready-made solution. For example, you can install the MoreLinq package via nuget and use just

     using MoreLinq; 
     A best = arr.MinBy(a => a.value);