C# 在单个LINQ查询中获取最大值和最小值
我有一组具有两个属性的对象,a和B。我想得到a的最小值和B的最大值 乙二醇 使用LINQ查询语法,是否有一种方法可以做到这一点,使其只在集合上传递一次C# 在单个LINQ查询中获取最大值和最小值,c#,linq,C#,Linq,我有一组具有两个属性的对象,a和B。我想得到a的最小值和B的最大值 乙二醇 使用LINQ查询语法,是否有一种方法可以做到这一点,使其只在集合上传递一次 所需的结果将是匿名类型,例如results.MinA=x,results.MaxB=y 我之前的回答不起作用 我回到这里,尝试了几个不同的答案,最终得到了这个解决方案,如前所述 var values = new List<int> {1, 2, 3, 4, 5}; var maxmin = new {
所需的结果将是匿名类型,例如results.MinA=x,results.MaxB=y 我之前的回答不起作用 我回到这里,尝试了几个不同的答案,最终得到了这个解决方案,如前所述
var values = new List<int> {1, 2, 3, 4, 5};
var maxmin = new {min = values.Min(), max = values.Max()};
您可以使用聚合方法
您可以使用对象作为结果的容器,并使用Math.Min和Math.Max整理语法:
var maxmin = objects.Aggregate(objects[0], (i, j) =>
new YourObject { A = Math.Min(i.A, j.A), B = Math.Max(i.B, j.B) });
最小值和最大值都是聚合。一般的linq聚合函数是 假设属性A是一个整数,B是一个字符串,您可以这样写:
objects.Aggregate(
new {
MinA = int.MaxValue,
MaxB = string.Empty
},
(accumulator, o) => new {
MinA = Math.Min(o.A, accumulator.MinA),
MaxB = o.B > accumulator.MaxB ? o.B : accumulator.MaxB
});
我知道您想要一个Linq查询,但我不能停止指出非Linq版本可能更具可读性。比较一下:
IEnumerable<Message> messages = SomeMessages();
Func<DateTime, DateTime, DateTime> min = (dt1, dt2) => dt1 > dt2 ? dt2 : dt1;
Func<DateTime, DateTime, DateTime> max = (dt1, dt2) => dt1 > dt2 ? dt1 : dt2;
// linq version
var result = messages.Aggregate(
new { StartDate = DateTime.MaxValue, EndDate = DateTime.MinValue }, /* initial value */
(accumulate, current) => new { StartDate = min(accumulate.StartDate, current.ReceivedTime), EndDate = max(accumulate.EndDate, current.ReceivedTime) });
// non-linq version
DateTime start = DateTime.MaxValue;
DateTime end = DateTime.MinValue;
foreach (DateTime dt in messages.Select(msg => msg.ReceivedTime))
{
start = min(start, dt);
end = max(end, dt);
}
如果要从对象列表中获取最小值和最大值,并且不希望按属性分组,则可以使用以下linq:
var val = new List<dynamic>{
new { A=1, B=1 },
new { A=2, B=2 },
new { A=3, B=4 }
};
var minMax = val.GroupBy(f => string.Empty).Select(f => new
{
Min = f.Min(g => g.A),
Max = f.Max(g => g.B)
}).FirstOrDefault();
根据单个linq查询的定义,这非常适合扩展方法
public static MinAndMax<T> MinAndMax<T>(this IEnumerable<T> source)
where T : IComparable<T>
{
Ensure.NotNullOrEmpty(source, nameof(source));
using (var enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
var min = enumerator.Current;
var max = enumerator.Current;
while (enumerator.MoveNext())
{
if (Comparer<T>.Default.Compare(enumerator.Current, min) < 0)
{
min = enumerator.Current;
}
if (Comparer<T>.Default.Compare(enumerator.Current, max) > 0)
{
max = enumerator.Current;
}
}
return new MinAndMax<T>(min, max);
}
throw new InvalidOperationException("Sequence contains no elements.");
}
}
public struct MinAndMax<T>
where T : IComparable<T>
{
public MinAndMax(T min, T max)
{
this.Min = min;
this.Max = max;
}
public T Min { get; }
public T Max { get; }
}
与非优化解没有任何区别。它实际上不起作用,因为o不是IEnumerable,等等,所以没有最小或最大函数。因此,它不会构建一行let min=o.Mino=>o.AThe问题询问LINQ查询语法,与lambda扩展方法相反。。。不确定这对cyrus是否重要。@MattTester我认为他首先想要单通道,其次是查询样式,为什么不编写自己的扩展方法,遍历对象范围一次并返回元组或其他什么?这几乎是猜测,所以我道歉,但是在一次传递中获得min和maz是这样的:如果num>max,那么max。否则如果num
var val = new List<dynamic>{
new { A=1, B=1 },
new { A=2, B=2 },
new { A=3, B=4 }
};
var minMax = val.GroupBy(f => string.Empty).Select(f => new
{
Min = f.Min(g => g.A),
Max = f.Max(g => g.B)
}).FirstOrDefault();
public static MinAndMax<T> MinAndMax<T>(this IEnumerable<T> source)
where T : IComparable<T>
{
Ensure.NotNullOrEmpty(source, nameof(source));
using (var enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
var min = enumerator.Current;
var max = enumerator.Current;
while (enumerator.MoveNext())
{
if (Comparer<T>.Default.Compare(enumerator.Current, min) < 0)
{
min = enumerator.Current;
}
if (Comparer<T>.Default.Compare(enumerator.Current, max) > 0)
{
max = enumerator.Current;
}
}
return new MinAndMax<T>(min, max);
}
throw new InvalidOperationException("Sequence contains no elements.");
}
}
public struct MinAndMax<T>
where T : IComparable<T>
{
public MinAndMax(T min, T max)
{
this.Min = min;
this.Max = max;
}
public T Min { get; }
public T Max { get; }
}
var minMax = xs.MinAndMax();