tags:

views:

81

answers:

5

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 control with the lowest Y value (top control) from the collection.

An example would be most appreciated !

+4  A: 

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.

Simon Steele
thanx for your time Simon !
no9
@Simon, shouldn't it be c.Location.Y?
Nathan Koop
@Nathan Koop: It should be now, when I wrote it the question stated X :)
Simon Steele
this works, but with .Last and not with .First.If i use .First the control that gets removed has larger Y value.
no9
Just to nitpick, it actually goes through the list 3 times, not twice. The third time is in `collection.Remove`. If we're really worried about performance here, the best way would be a simple `for` loop to find the lowest `Y` value *and* the index of the control with that value in one sweep through the list. Then `collection.RemoveAt` wouldn't need to search through the list again. If performance isn't an issue—and unless there were many, *many* controls, I don't imagine it would be—I would prefer your first example, as it's briefer, and IMO, easier to read.
P Daddy
@no9: I can't see how either of Simon's code samples would give you the control with the *largest* `Y` value. `First` is indeed the correct function.
P Daddy
@P Daddy: Yup, thanks, was only thinking about the Linq parts. Corrected to three times.
Simon Steele
A: 

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)
   )
);
Musa Hafalır
A: 
collection.Remove( collection.Min( c => c.Y ));
amaca
`collection.Min( c => c.Y )` returns the minimum Y coordinate. As `collection.Remove` expects a control, this statement will result in a compile error.
kbrimington
A: 

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);
Dan Tao
LINQ is fine for modifying data. Structured Query Language is also for querying data, of course, and if you want to modify it you should use something else.
amaca
@amaca: LINQ is "fine for modifying data" in the sense that it *can* be used for this purpose. Side-effects cannot really be ensured against, except by the caller. But it really isn't *intended* for that purpose. To quote [Eric Lippert](http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx): "The purpose of an expression is to compute a value, not to cause a side effect."
Dan Tao
A: 

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);
Jerome