C# 林克问题。。。需要获取具有最小值的元素
我是linq的新手,所以我仍然在努力 我有一个控件集合(每个控件都有一个类型为Point的位置)。 我需要从集合中删除Y值最低的控件(顶部控件) 最好举个例子 类似这样:C# 林克问题。。。需要获取具有最小值的元素,c#,linq,C#,Linq,我是linq的新手,所以我仍然在努力 我有一个控件集合(每个控件都有一个类型为Point的位置)。 我需要从集合中删除Y值最低的控件(顶部控件) 最好举个例子 类似这样: collection.Remove(collection.OrderBy(c => c.Location.Y).First()); collection .Remove(collection .Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ?
collection.Remove(collection.OrderBy(c => c.Location.Y).First());
collection
.Remove(collection
.Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ? c1 : c2)
)
);
订购相当昂贵,因此根据您的用例,您还可以找到具有最低值的项目,然后将其删除:
collection.Remove(collection.First(c => c.Y == collection.Min(c2 => c2.Y)));
这最多会枚举列表三次,一般来说,这应该比OrderBy更快,但是如果性能对您很重要,那么请首先进行测量。您只需要找到该项并将其删除,这是肯定的。Remove非常清楚,但在查找时,可以使用如下聚合方法:
collection.Remove(collection.OrderBy(c => c.Location.Y).First());
collection
.Remove(collection
.Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ? c1 : c2)
)
);
收藏
.删除(收藏)
.聚合((c1,c2)=>c1.点Y
记住,LINQ代表语言集成查询。也就是说,它被用作查询工具,而不是修改集合
也就是说,您可以使用LINQ找到需要删除的控件。然后简单地以正常方式移除它
// Let's say controls is a ControlCollection
var enumerable = controls.Cast<Control>();
int minimumY = enumerable.Min(c => c.Location.Y);
Control topControl = enumerable.Where(c => c.Location.Y == minimumY);
controls.Remove(topControl);
//假设controls是ControlCollection
var enumerable=controls.Cast();
int minimumY=enumerable.Min(c=>c.Location.Y);
Control topControl=enumerable.Where(c=>c.Location.Y==minimumY);
控制。移除(顶部控制);
订购更贵。只要得到最小值
var lowest = (from c in collection
where c.X == collection.Min(i => i.X)
select c).FirstOrDefault();
collection.Remove(c);
下面是一个扩展方法,允许您选择最小元素而不是最小值。您可以这样使用:
collection.Remove(collection.OrderBy(c => c.Location.Y).First());
collection
.Remove(collection
.Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ? c1 : c2)
)
);
var lower=collection.MinElement(x=>x.Y)代码>
然后您可以使用集合删除元素。删除(最低)
publicstatict MinElement(此IEnumerable源代码,Func选择器){
if(source==null){
抛出新ArgumentNullException(nameof(source));
}
int minValue=0;
T minElement=默认值(T);
bool hasValue=false;
foreach(源中的ts){
int x=选择器;
if(hasValue){
如果(x<最小值){
最小值=x;
minElement=s;
}
}否则{
最小值=x;
minElement=s;
hasValue=true;
}
}
if(hasValue){
返回元素;
}
抛出新的InvalidOperationException(“MinElement:序列中没有元素”);
}
不使用“选择”,因此您可能需要更改问题的标题。也许您指的是最低Y(最高控制)!您应该按Y值升序排列集合,然后选择第一个值。@chiccodoro thanx,真的不知道该问什么:)@VinayC是的,太简单了,想不起来……如果您谈论的是Win Forms控件中的控件
属性,然后,在使用Linq方法之前,必须使用Enumerable.Cast
。collection.Min(c=>c.Y)
返回最小Y坐标。由于collection.Remove
需要一个控件,此语句将导致编译错误。@Simon,它不应该是c.Location.Y吗?@Nathan Koop:现在应该是了,当我写它时,问题是X:)这是有效的,但是使用.Last而不是.First。如果我使用。首先,被删除的控件有较大的Y值。只是吹毛求疵,它实际上会在列表中遍历3次,而不是两次。第三次在集合中。删除。如果我们真的担心这里的性能,最好的方法是一个简单的for
循环,在列表的一次扫描中找到最低的Y
值和具有该值的控件索引。然后,collection.RemoveAt
就不需要再次搜索列表了。如果性能不是一个问题,除非有很多很多控件,否则我不认为会是-我更喜欢你的第一个示例,因为它更简短,而且我更容易阅读。@no9:我看不出Simon的两个代码示例如何为你提供具有最大Y
值的控件First
确实是正确的函数。LINQ可以修改数据。当然,结构化查询语言也用于查询数据,如果您想修改它,应该使用其他语言。@amaca:LINQ“适合修改数据”,因为它可以用于此目的。除了调用者之外,不能真正确保不会产生副作用。但它真的不是为了这个目的。引用:“表达式的目的是计算一个值,而不是引起副作用。”这是一个很好的答案。只需对集合进行一次迭代即可找到该项,而不是两次。它可以轻松地用作创建扩展方法的起点,如MinBy()
或MaxBy()
。