the*_*rrs 264 c# linq object max
我有一个具有两个int属性的对象列表.该列表是另一个linq查询的输出.物体:
public class DimensionPair
{
public int Height { get; set; }
public int Width { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想找到并返回列表中具有最大Height属性值的对象.
我可以设法获得值的最高值,Height但不能获得对象本身.
我可以用Linq做到这一点吗?怎么样?
Jon*_*eet 265
我们有一个扩展方法,可以在MoreLINQ中完成此操作.您可以查看那里的实现,但基本上是迭代数据的情况,记住我们到目前为止看到的最大元素以及它在投影下产生的最大值.
在你的情况下你会做类似的事情:
var item = items.MaxBy(x => x.Height);
Run Code Online (Sandbox Code Playgroud)
除了Mehrdad的第二个解决方案(基本相同)之外,这比其他任何解决方案更好(IMO MaxBy):
Max的值,然后找出与该值的第一个元素是O(n),但在序列迭代两次.在可能的情况下,您应该以单通方式使用LINQ.Meh*_*ari 195
这需要排序(O(n log n)),但非常简单和灵活.另一个优点是能够将它与LINQ to SQL一起使用:
var maxObject = list.OrderByDescending(item => item.Height).First();
Run Code Online (Sandbox Code Playgroud)
请注意,这具有list仅枚举序列一次的优点.虽然在此期间如果不改变可能无关紧要,但它对任意对象list都很List<T>重要IEnumerable<T>.没有什么能保证序列在不同的枚举中不会改变,因此多次执行它的方法可能是危险的(并且效率低,取决于序列的性质).然而,对于大型序列来说,它仍然不是理想的解决方案.我建议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;
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它:
var maxObject = list.MaxObject(item => item.Height);
Run Code Online (Sandbox Code Playgroud)
Cam*_*and 137
进行订购然后选择第一项是浪费了大量时间在第一项之后订购商品.你不关心那些的顺序.
相反,您可以使用聚合函数根据您要查找的内容选择最佳项目.
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);
Run Code Online (Sandbox Code Playgroud)
Dra*_*ouf 33
你为什么不尝试这个?:
var itemsMax = items.Where(x => x.Height == items.Max(y => y.Height));
Run Code Online (Sandbox Code Playgroud)
或者更优化:
var itemMaxHeight = items.Max(y => y.Height);
var itemsMax = items.Where(x => x.Height == itemMaxHeight);
Run Code Online (Sandbox Code Playgroud)
嗯?
meu*_*rus 21
到目前为止答案很棒!但我认为需要一个具有以下约束的解决方案:
这里是:
public static T MaxBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R> {
return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) > 0 ? next : max).Item1;
}
public static T MinBy<T, R>(this IEnumerable<T> en, Func<T, R> evaluate) where R : IComparable<R> {
return en.Select(t => new Tuple<T, R>(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) < 0 ? next : max).Item1;
}
Run Code Online (Sandbox Code Playgroud)
用法:
IEnumerable<Tuple<string, int>> list = new[] {
new Tuple<string, int>("other", 2),
new Tuple<string, int>("max", 4),
new Tuple<string, int>("min", 1),
new Tuple<string, int>("other", 3),
};
Tuple<string, int> min = list.MinBy(x => x.Item2); // "min", 1
Tuple<string, int> max = list.MaxBy(x => x.Item2); // "max", 4
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
348039 次 |
| 最近记录: |