Blog de Nicoloco

ASP.NET – Entity Framework – Windows Azure – How To | Todo en C#

  • MVP Visual C#

  • MCC 2011

    MCC 2011
  • MCS Colombia

    Microsoft Community Specialist
  • Comunidades

    Lider de BogotaDotNet
  • Encuentrame en

    Sigueme en Twitter
  • Mi perfil de LinkedIn

Archivos de la categoría ‘Linq’

[Linq] Eficiencia Count() vs. Any()

Publicado por nicolocodev en 20 mayo, 2012

El tema de la eficiencia se está volviendo importante, siempre lo ha sido, pero ahora más que nunca dado que los Frameworks nos brindan tantas abstracciones que podemos terminar haciendo lo mismo de una u otra forma sin preocuparnos por el que hace de fondo determinada función, y ese es el caso de estas dos sentencias. Dada una lista de la forma:

            List<string> palabras = new List<string>();
            palabras.Add("Primera");
            palabras.Add("Segunda");
            palabras.Add("Tercera");

Podemos entonces comprobar la existencia de elementos de las dos siguiente maneras:

            bool contieneElementosCount = palabras.Count() > 0;
            bool contieneElementosAny = palabras.Any();

Ambas nos devolverán true o false según corresponda, pero lo harán de forma diferente, y aquí es donde debemos empezar a evaluar que no conviene más, por un lado tenemos la función Count() que si miramos la documentación oficial de MSDN veremos que dice claramente, “Si el tipo de source implementa ICollection<T>, esa implementación se utiliza para obtener el recuento de elementos. De lo contrario, este método determina el recuento.” Pero ¿qué quiere decir con esto? Pues simple, si vemos la interfaz ICollection podemos ver que una de sus propiedades es Count, es decir que acudir este método intentara hacer algo como lo siguiente:

            ICollection<string> collection = palabras as ICollection<string>;
            int numeroElementos = collection.Count;

Cosa que para una colección que implementa de ICollection como lo hace List<T> no tiene ningún inconveniente, y como es el caso de todas las colecciones del espacio de nombres de System.Collection.Generic
pues todas implementan de la interfaz genérica ICollection. La excepción no sabría con que colección se presentaría y por lo tanto me parece la más rápida pues solo se debe hacer un casteo [de hecho ni se hace] para obtener el valor de count. El problema radica en que nos arriesgamos a tener una colección que no implemente de este y deba hacer el conteo manual [dentro de un while] y además de preguntar del lado de la linq por n > 0, haces un paso más y te arriesgas el doble.

Por el otro lado tenemos a Any(), este método determina si una secuencia contiene elementos. [*tomado de MSDN] de una forma un poco más directa, acudiendo directamente al método MoveNext de la enumeración pero sin tener que iterar sobre todos ellos, es decir, hará algo como lo siguiente:

            bool contieneElementos;
            using (IEnumerator<string> enumerator = palabras.GetEnumerator())
            {
                contieneElementos = enumerator.MoveNext();
            }

Entonces como podemos ver Any() es un método especialmente diseñado para este propósito y no se debe confundir con una “variación” de Count(), pues su propósito no es ese, si no el de determinar la cantidad de elementos de una colección.

Espero les sea de utilidad.

Hasta el próximo post.

Publicado en C#.NET, Linq | 10 Comentarios »

[Linq] Aplicar varios Order en una consulta

Publicado por nicolocodev en 5 mayo, 2012

Hola, en los foros siempre se ve la pregunta de por qué al aplicar dos OrderBy seguidos no se obtiene el resultado esperado. Bien en este post mostrare la forma de hacerlo.
Teniendo el siguiente código:

    public class Producto
    {
        public string Nombre { getset; }

        public int Precio { getset; }
    }    
    class Program     {         static void Main(string[] args)         {             List<Producto> productos = new List<Producto>                                            {                                                new Producto {Nombre = "Computadora", Precio = 200},                                                new Producto {Nombre = "Televisor", Precio = 150},                                                new Producto {Nombre = "Impresora", Precio = 350}                                            };             List<Producto> prdsOrdenado = productos.OrderBy(x => x.Nombre).OrderBy(y => y.Precio).ToList();                     }     }

Obtendremos el siguiente resultado

Como se puede ver, el segundo OrderBy sobrescribe al primero ignorando el orden que este ya había aplicado, para lograr el resultado esperado, acudimos al método ThenBy.

El código quedaría de la forma:

    class Program
    { 
        static void Main(string[] args) 
        { 
            List<Producto> productos = new List<Producto> 
                                           { 
                                               new Producto {Nombre = "Computadora", Precio = 200}, 
                                               new Producto {Nombre = "Televisor", Precio = 150}, 
                                               new Producto {Nombre = "Impresora", Precio = 350} 
                                           }; 
            List<Producto> prdsOrdenado = productos.OrderBy(x => x.Nombre).ThenBy(y => y.Precio).ToList();             
        } 
    } 

Y obtendremos el siguiente resultado

NOTA: Si deseas usar el orden descendente deberás acudir al método ThenByDescending

Espero les sea de utilidad.

Hasta el próximo post.

Publicado en C#.NET, Linq | 1 comentario

[Linq] Tomar e ignorar valores de un origen de datos

Publicado por nicolocodev en 30 julio, 2011

Hola, en ocasiones necesitamos mostrar solo una parte del resultado de una consulta Linq, algo así como lo haríamos con un Top de SQL, bien, pues esta no es una limitante para Linq pues entre unos de los tantos y tan sobre cargados métodos de Enumerable tenemos esta funcionalidad.

El método Take nos permite obtener los primeros n resultados de una lista de valores, por ejemplo:

string[] paises = { “Colombia”, “Bolivia”, “Argentina”, “Venezuela”, “Perú” };
var primeros3paises = paises.Take(3);
Console.WriteLine(“El top tres de paises latinoamericanos”);
foreach (var pais in primeros3paises)
{
                Console.WriteLine(pais);
}

El resultado de esta consulta nos arrojara una lista con los tres primeros tres países de nuestro origen de datos.

Por si fuera poco Enumerable tiene un método que nos permite ignorar los primeros n elementos en una lista de datos, este método es Skip, veamos un ejemplo:

string[] paises = { “Colombia”, “Bolivia”, “Argentina”, “Venezuela”, “Peru” };
var  ultimos2paises = paises.Skip(3);
Console.WriteLine(“Los dos últimos países de la lista son: “);
foreach (var pais in ultimos2paises)
{
                Console.WriteLine(pais);
}

El resultado de esta consulta nos arrojara una lista con los dos últimos países de la lista.

Bien, pero si ahora no supiéramos el numero de valores que necesitaremos seleccionar/ignorar, y que este por el contrario dependiera de una expresión? por fortuna para nosotros Enumerable tiene la respuesta, en este encontramos los métodos TakeWhile y SkipWhile, veamos un ejemplo:

int[] numeros = { 0,1,4,5,2,6,3,9,7,8 };
var primerosMenoresque5 = numeros.TakeWhile(n => n < 5);
Console.WriteLine(“Primeros números menores que 5:”);
foreach (var num in primerosMenoresque5 )
{
        Console.WriteLine(num);
}

El metodo TakeWhile nos retornara una lista con los valores mientras la condición marcada se cumpla, es decir, recorrerá cada uno de los items de la colección comparándolo con la expresión indicada, en el momento que sea false dejara de compararse con los demás valores de la colección. Teniendo esto claro el resultado de esa expresión sera una colección con los valores 0,1,4.

El método SkipWhile funciona de una manera similar, solo que ignorara los valores que cumplan con la condición indicada, mientras el resultado de la comparación sea true. Teniendo esto claro el resultado de hacer un SkipWhile(n=> n < 5) a la lista de valores del ejemplo anterior nos daría: 5, 2, 6, 3, 9, 7, 8.

Espero les haya quedado claro el uso de estos útiles métodos, sino no duden en escribir un comentario con su duda para que sea aclarada.

Hasta el próximo post.

Publicado en C#.NET, Linq | 2 Comentarios »

Let de Linq – Declarando variables dentro de nuestra consulta

Publicado por nicolocodev en 30 julio, 2011

Hola, en ocasiones dentro de nuestras consultas Linq necesitamos almacenar el resultado de una operación matemática o la comparación de una cadena, etc, etc. Para ello podemos usar la palabra clave let esta nos creara una nueva variable de rango dentro de la consulta y la inicializara con el resultado de la expresión que le asignemos.

Ejemplo, supongamos que recuperamos una lista de precios y tenemos un interés variable que aplicarle a estos y ademas el resultado de nuestra consulta deberá mostrar solo los precios que con dicho interés sean inferiores a $800, con linq esto es muy sencillo:

double[] precios = { 500, 300, 450, 250 };
double interes = 2.5;
var valores =
from prc in precios
 let precioInteres = prc * interes
 where precioInteres <= 800
 select new { prc, precioInteres };
 Console.WriteLine(“Totales inferiores a $800″);
 foreach (var valor in valores)
 {
                Console.WriteLine(“Precio sin interés: {0} – Con Interes: {1}”, valor.prc, valor.precioInteres);
}

Como podemos notar hemos declarado una variable de rango nueva con la que podemos trabajar, y haciendo uso de los tipos anónimos creamos un objeto con las propiedades prc y precioInteres.

Sin embargo estas variables de rango declaradas con let tienen una insignificante limitación (comparada con lo útiles que son) y es que una vez después de inicializadas no se pueden reasignar :( ,pero si podemos crear mas variables de rango a partir de ellas :) .

Espero les sea de utilidad así como lo es para mi

Hasta el próximo post.

Publicado en C#.NET, Linq | Deja un Comentario »

[Linq] Obtener los Radiobuttons a partir de su GroupName

Publicado por nicolocodev en 31 mayo, 2011

Hola, hoy en la mañana cuando llegue ala oficina y empece a revisar los foros, me encontré con una pregunta curiosa (“Obtener todos los radiobuttons a partir del GroupName“)… entonces pensé, – este hombre necesita saber el poder de Linq, así que le respondí de la siguiente forma.

En un escenario como el siguiente, una pagina web con seis Radiobuttons, separados en dos grupos de tres (“Grupo1″ y “Grupo2″) y un botón que desencana la acción.

Bien, teniendo claro esto, manos al teclado, lo primero para poder trabajar con Linq (en este caso) es tener una colección IEnumerable del tipo RadioButton que contendra todos los controles de este tipo, así:

IEnumerable<RadioButton> allRadios = Page.Form.Controls.OfType<RadioButton>();

Como vemos en la anterior linea de código accedemos a los controles del Form de la pagina y acudimos al metodo extensor OfType siendo T la clase por la que debemos “filtrar”. Como el extensor OfType retorna un IEnumarable (no un ControlCollection) ya tenemos acceso a todo el poder de Linq.

Ahora nos queda filtrar por el nombre de grupo, para esto he creado una función llamada getByGroupName, así:

private IEnumerable<RadioButton> getByGroupName(IEnumerable<RadioButton> allRadios, string groupName)
{
        return from radios in allRadios
               where radios.GroupName == groupName
               select radios;
}

De esta forma, haciendo uso de Linq dejamos de usar iteradores y hardcode pues le agregamos un tanto mas de dinamismo a este tipo de trabajos.

Pero bueno, y si ahora queremos saber cuales de este grupo están seleccionados o no?.. fácil, la respuesta es Linq. Para esto creamos otro método al que llamaremos getAllCheckeds, así:

private IEnumerable<RadioButton> getAllCheckeds(IEnumerable<RadioButton> byGroupname, bool check)
{
        return from radios in byGroupname
               where radios.Checked == check
               select radios;
}

De esta forma podemos obtener toda la información que queramos de nuestros controles, haciendo uso de linq. Finalmente, para el que se le dificulte el entendimiento del código, aquí lo dejo todo ( mas abajo el link de descarga):

protected void Button1_Click(object sender, EventArgs e)
{
        IEnumerable<RadioButton> allRadios = Page.Form.Controls.OfType<RadioButton>();
        IEnumerable<RadioButton> byGroupname = getByGroupName(allRadios, “Grupo1″);
        IEnumerable<RadioButton> radioCheked = getAllCheckeds(byGroupname, true);     
}

private IEnumerable<RadioButton> getByGroupName(IEnumerable<RadioButton> allRadios, string groupName)
{
        return from radios in allRadios
               where radios.GroupName == groupName
               select radios;
}
private IEnumerable<RadioButton> getAllCheckeds(IEnumerable<RadioButton> byGroupname, bool check)
{
        return from radios in byGroupname
               where radios.Checked == check
               select radios;
}

Por ser este mi primer post de Linq, les dejo un link a la documentacion del MSDN, es muy buena.

Espero les sea de utilidad, hasta el próximo post.

Descarga el ejemplo.

Publicado en ASP.NET, C#.NET, Linq | 1 comentario

 
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 57 seguidores

%d bloggers like this: