Herramientas de usuario

Herramientas del sitio


fw:othersnet:linq

¡Esta es una revisión vieja del documento!


LINQ

En System.Linq existen una serie de métodos de extensión que permiten hacer consultas sobre datos (sobre xml, bases de datos…).

Los siguientes son ejemplos de consultas sobre elementos en memoria:

IEnumerable<Person> list = lPerson.Where(p ⇒ p.firstName.StartsWith(“A”)); int maxAge = lPerson.Max(p ⇒ p.age); double avg = lPerson.Average(p ⇒ p.age);

Pero en LINQ existen lo que serían las sintaxis de expresiones para realizar este tipo de consultas. Estas son parecidas a las sentencias sql de toda la vida y empiezan siempre por from y acaban por select siguiendo una estructura como la que sigue: from elementos_a_consultar in lista select elementos_devueltos

Un ejemplo: IEnumerable<Person> list = from p in lPerson select p;

También podemos agregar clausulas where y orderby: IEnumerable<Person> list = from p

  in lPerson 
  where p.firstName.StartsWith("A")
  orderby p.age
  select p;

En el código de arriba el trozo “from p in lPerson” indica lanzar una consulta LINQ sobre la colección “lPerson”, y que usaremos el parámetro “p” para representar a cada elemento que consultamos. En realidad, el nombre del parámetro “p” es irrelevante - podría haberlo llamado “o”, “x”, “person” o de cualquier otra forma. El trozo “select p” nos indica que queremos devolver una secuencia IEnumerable de objetos Person como resultado de la consulta. Esto esto pasa porque la colección “lPerson” contiene objetos de tipo “Person”. Pero si quisieramos devolver los nombres sería algo así: IEnumerable<string> list = from p

  in lPerson 
  where p.firstName.StartsWith("A")
  orderby p.age
  select p.firstName;

También podemos consultar los elementos relacionados o ordendar descendentemente: IEnumerable<string> categories = from c in Categories

where c.Products.Count > 5
orderby c.CategoryName descending
select c.CategoryName;

Otro ejemplo sería el de devolver un objeto de una clase que no es la de los elementos de la lista: class AlternatePerson {

string nameAge { get; set; }

} … IEnumerable<AlternatePerson> friends = from p in lPeople

where p.LastName.StartsWith("G")
select new AlternatePerson {
	nameAge = p.FirstName + p.Age;
}

Una de las principales características de la interface IEnumerable<T> es que los objetos que las implementen pueden retrasar su ejecución hasta el momento en que se introduzca en un bucle (esto es posible gracias al “yield”). LINQ usa esta ventaja, retrasando las consultas hasta la primera vez que se itere sobre el resultado. Si nunca se itera sobre una IEnumerable<T>, entonces, la consulta nunca es ejecutada. Pero si lo que queremos es ejecutar inmediatamente la consulta (utilizando toList o toArray) haremos: List<Category> categories = (from c in db.Categories

where c.CategoryName
select c).ToList();

Si luego cambiasemos los datos de la lista inicial y volviesemos a iterarla, se volvería a ejecutar la query. Por ejemplo, en la siguiente aparece Juanjo en la segunda iteración: var list = from l in lPerson select l; foreach (Person p in list)

  Console.WriteLine(p.firstName);

lPerson.Add(new Person() { firstName = “Juanjo”, age = 32 }); foreach (Person p in list)

  Console.WriteLine(p.firstName);

Ejemplos: Where + and var expensiveInStockProducts =

      from p in products
      where p.UnitsInStock > 0 && p.UnitPrice > 3.00M
      select p;

Buscar las palabras que tengan más letras que su valor string[] digits = { “zero”, “one”, “two”, “three”, “four”, “five”, “six”, “seven”, “eight”, “nine” }; var shortDigits = digits.Where((digit, index) ⇒ digit.Length < index);

Cambiando el valor int[] numbers = { 5, 4, 1}; var numsPlusOne =

      from n in numbers
      select n + 1;

Devolvería 6 5 2

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; string[] strings = { “zero”, “one”, “two”, “three”, “four”, “five”, “six”, “seven”, “eight”, “nine” }; var textNums =

      from n in numbers
      select strings[n];

Grouping Coger una agrupación y el tipo de agrupación que es: var wordGroups =

              from w in words
              group w by w[0] into g
              select new { FirstLetter = g.Key, Words = g };

Anidación var customerOrderGroups =

              from c in customers
              select
                  new {c.CompanyName,
                       YearGroups =
                           from o in c.Orders
                           group o by o.OrderDate.Year into yg
                           select
                               new {Year = yg.Key,
                                    MonthGroups =
                                        from o in yg
                                        group o by o.OrderDate.Month into mg
                                        select new { Month = mg.Key, Orders = mg }
                                   }
                      };

Tipado anónimo string[] words = { “aPPLE”, “BlUeBeRrY”, “cHeRry” }; var upperLowerWords =

      from w in words
      select new {Upper = w.ToUpper(), Lower = w.ToLower()};

foreach (var ul in upperLowerWords) {

      Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);

Otro… var productInfos =

      from p in products
      select new {p.ProductName, p.Category, Price = p.UnitPrice};

foreach (var productInfo in productInfos) {

      Console.WriteLine("{0} is in the category {1} and costs {2} per unit.", productInfo.ProductName, productInfo.Category, productInfo.Price);

Otro… int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var numsInPlace = numbers.Select((num, index) ⇒ new {Num = num, InPlace = (num == index)});

Otro… con asignación var orders =

      from c in customers,
              o in c.Orders,
              total = o.Total
      where total >= 2000.0M
      select new {c.CustomerID, o.OrderID, total};

Relación de tablas var orders =

      from c in customers
      where c.Region == "WA"
      from o in c.Orders
      where o.OrderDate >= cutoffDate
      select new {c.CustomerID, o.OrderID};

Orderby var sortedWords =

      from w in words
      orderby w.Length
      select w;

Cambiar el orden var reversedIDigits = (

      from d in digits
      where d[1] == 'i'
      select d)
      .Reverse();

Counts int[] factors = { 2, 2, 3, 5, 5 }; int uniqueFactors = factors.Distinct().Count(); Devolvería 3

Contar los impares: int oddNumbers = numbers.Count(n ⇒ n % 2 == 1);

Contar los carácteres de todas las palabras string[] words = { “cherry”, “apple”, “blueberry” }; double totalChars = words.Sum(w ⇒ w.Length);

Concatenar dos resultados var customerNames =

      from c in customers
      select c.CompanyName;

var productNames =

      from p in products
      select p.ProductName;

var allNames = customerNames.Concat(productNames);

Escoger elementos El primero Product product12 = (

      from p in products
      where p.ProductID == 12
      select p )
      .First();

El cuarto… int fourthLowNum = (

      from n in numbers
      where n < 5
      select n )
      .ElementAt(3);

Nuevas funciones Generación de los números de 100 a 150: from n in Sequence.Range(100, 50)

Repetición del número 7, 10 veces: var numbers = Sequence.Repeat(7, 10);

Función Distinct Coge sólo uno, esquivando los elementos duplicados var categoryNames = (

      from p in products
      select p.Category)
      .Distinct();

Función Union Une dos listas del mismo tipo var uniqueNumbers = numbersA.Union(numbersB);

Función Intersect Coge los elementos que se repiten en las dos listas var commonNumbers = numbersA.Intersect(numbersB);

Función Except Coge los elementos de la primera lista que no esten en la segunda IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB);

Función Take Coge los primeros valores var first3Numbers = numbers.Take(3);

var first3WAOrders = (

              from c in customers
              from o in c.Orders
              where c.Region == "WA"
              select new {c.CustomerID, o.OrderID, o.OrderDate} )
              .Take(3);

Función Skip Coge los últimos números saltandose los indicados var allButFirst4Numbers = numbers.Skip(4);

Combinación de skip y take query.Skip(30).Take(10)

fw/othersnet/linq.1237795016.txt.gz · Última modificación: 2020/05/09 09:24 (editor externo)