LINQ question ... need to get element with min value
Im new to linq so i still struggle ....
I have a collection of controls (each has a Location of type Point). I need to remove the contro开发者_如何学JAVAl with the lowest Y value (top control) from the collection.
An example would be most appreciated !
Something like this:
collection.Remove(collection.OrderBy(c => c.Location.Y).First());
The ordering is quite expensive, so depending on your use-case you could also find the item with the lowest value and then remove it:
collection.Remove(collection.First(c => c.Y == collection.Min(c2 => c2.Y)));
This enumerates the list up to three times, generally this should still be faster than the OrderBy, but if performance is important to you then measure first.
You just need to find the item and remove it, that's for sure. Remove is very clear, but while finding, you can use Aggregate method like this:
collection
.Remove(collection
.Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ? c1 : c2)
)
);
Ordering is more expensive. Just get the min value.
var lowest = (from c in collection
where c.X == collection.Min(i => i.X)
select c).FirstOrDefault();
collection.Remove(c);
Remember that LINQ stands for Language INtegreated Query. That is, it's meant to be used as a tool for querying, not for modifying collections.
That said, you could find the control you need to remove using LINQ. Then simply remove it the normal way.
// 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);
Below is an extension method that allows you to select min element as opposed to the min value. You can use like this:
var lowest = collection.MinElement(x => x.Y);
Then you can just remove the element with collection.Remove(lowest)
.
public static T MinElement<T>(this IEnumerable<T> source, Func<T, int> selector) {
if (source == null) {
throw new ArgumentNullException(nameof(source));
}
int minValue = 0;
T minElement = default(T);
bool hasValue = false;
foreach (T s in source) {
int x = selector(s);
if (hasValue) {
if (x < minValue) {
minValue = x;
minElement = s;
}
} else {
minValue = x;
minElement = s;
hasValue = true;
}
}
if (hasValue) {
return minElement;
}
throw new InvalidOperationException("MinElement: No elements in sequence.");
}
collection.Remove( collection.Min( c => c.Y ));
精彩评论