2010-08-26 8 views
8

Im nuevo a LINQ, así que todavía lucha ....LINQ pregunta ... necesidad de conseguir elemento con el valor min

tengo una colección de controles (cada uno tiene una ubicación de tipo Point). Necesito eliminar el control con el valor Y más bajo (control superior) de la colección.

¡Un ejemplo sería muy apreciado!

+0

no con "SELECCIONAR", por lo que es posible que desee cambiar el título de su pregunta. – chiccodoro

+0

Quizás te refieres a la Y más baja (el control más alto). Debe ordenar la colección ascendente por valor Y y luego elegir el Primer valor. – VinayC

+0

@chiccodoro thanx, realmente no sabía qué preguntar :) @VinayC sí, era demasiado simple para pensarlo ... – no9

Respuesta

11

Algo como esto:

collection.Remove(collection.OrderBy(c => c.Location.Y).First()); 

El orden es bastante caro, por lo que dependiendo de su caso de uso también se puede encontrar el elemento con el valor más bajo y luego eliminarla:

collection.Remove(collection.First(c => c.Y == collection.Min(c2 => c2.Y))); 

Esto enumera la lista hasta tres veces, generalmente esto debería ser más rápido que el OrderBy, pero si el rendimiento es importante para usted, primero mida.

+0

gracias por su tiempo Simon! – no9

+0

@Simon, ¿no debería ser c.Location.Y? –

+0

@Nathan Koop: Debería ser ahora, cuando lo escribí la pregunta declaró X :) –

6

Solo tiene que encontrar el artículo y quitarlo, eso es seguro. Quitar no está muy claro, pero al mismo tiempo encontrar, puede utilizar el método agregado como esto:

collection 
    .Remove(collection 
     .Aggregate((c1, c2) => c1.Point.Y < c2.Point.Y ? c1 : c2) 
    ) 
); 
+1

Esta es una gran respuesta. Requiere solo una iteración de la colección para encontrar el ítem, en lugar de dos. Se podría usar fácilmente como punto de partida para crear un método de extensión como 'MinBy()' o 'MaxBy()'. – gilly3

-1
collection.Remove(collection.Min(c => c.Y)); 
+4

'collection.Min (c => c.Y)' devuelve la coordenada Y mínima. Como 'collection.Remove' espera un control, esta declaración dará como resultado un error de compilación. – kbrimington

0

Recuerde que LINQ significa Lenguaje de consulta integreated . Es decir, está destinado a ser utilizado como una herramienta para consultas, no para que modifica las colecciones.

Dicho esto, puede encontrar el control que necesita para eliminar utilizando LINQ. Entonces simplemente quítalo de la manera normal.

// 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); 
+0

LINQ está bien para modificar datos. El lenguaje de consulta estructurado también es para consultar datos, por supuesto, y si desea modificarlo, debe usar algo más. – amaca

+0

@amaca: LINQ está "bien para modificar datos" en el sentido de que * puede * usarse para este propósito. En realidad, no se pueden garantizar los efectos secundarios, excepto por la persona que llama. Pero realmente no es * intencionado * para ese propósito. Para citar [Eric Lippert] (http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx): "El propósito de una expresión es calcular un valor, no causar un efecto secundario ". –

3

El pedido es más costoso. Solo consigue el valor mínimo.

var lowest = (from c in collection 
       where c.X == collection.Min(i => i.X) 
       select c).FirstOrDefault(); 
collection.Remove(c); 
0

A continuación se muestra un método de extensión que le permite seleccionar el elemento mínimo en lugar del valor mínimo. Se puede utilizar la siguiente manera:

var lowest = collection.MinElement(x => x.Y);

a continuación, puedes eliminar el elemento con 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."); 
} 
Cuestiones relacionadas