## GroupJoin - A resultSelector função é chamada apenas uma vez para cada outer elemento junto com uma coleção de todos os inner elementos que correspondem ao outer elemento. ```csharp= record Pessoa(string nome); record Fruta(string nome, Pessoa dono); Pessoa pedro = new Pessoa("Pedro"); Pessoa jorge = new Pessoa("Jorge"); Pessoa danilo = new Pessoa("Danilo"); Fruta abacaxi = new Fruta("Abacaxi", pedro); Fruta maca = new Fruta("Maça", pedro); Fruta banana = new Fruta("Banana", pedro); Fruta morango = new Fruta("Morango", danilo); List<Pessoa> pessoas = new List<Pessoa>() { pedro, jorge, danilo }; List<Fruta> frutas = new List<Fruta>() { abacaxi, maca, banana, morango }; var query = pessoas .GroupJoin(frutas, p => p, f => f.dono, (pessoas, frutaColecao) => new { NomeDono = pessoas.nome, Frutas = frutaColecao.Select(s => s.nome) }); foreach (var item in query) { Console.WriteLine($"Dono {item.NomeDono}, Frutas: {string.Join(",", item.Frutas)}"); } // Dono Pedro, Frutas: Abacaxi,Maça // Dono Jorge, Frutas: // Dono Danilo, Frutas: Morango ``` ## Join ```csharp= Pessoa pedro = new Pessoa("Pedro"); Pessoa jorge = new Pessoa("Jorge"); Pessoa danilo = new Pessoa("Danilo"); Fruta abacaxi = new Fruta("Abacaxi", pedro); Fruta maca = new Fruta("Maça", pedro); Fruta banana = new Fruta("Banana", pedro); Fruta morango = new Fruta("Morango", danilo); List<Pessoa> pessoas = new List<Pessoa>() { pedro, jorge, danilo }; List<Fruta> frutas = new List<Fruta>() { abacaxi, maca, banana, morango }; var query = pessoas .Join(frutas, p => p, f => f.dono, (pessoas, fruta) => new { NomeDono = pessoas.nome, Fruta = fruta.nome }); foreach (var item in query) { Console.WriteLine($"Dono {item.NomeDono}, Frutas: {item.Fruta}"); // Dono Pedro, Frutas: Abacaxi // Dono Pedro, Frutas: Maça // Dono Pedro, Frutas: Banana // Dono Danilo, Frutas: Morango } Console.ReadKey(); ``` - Join preserva a ordem dos elementos de outer e para cada um desses elementos, a ordem dos elementos correspondentes de inner. - Um GroupJoin é em SQL o que chamamos de “Left Outer JOIN”, enquanto um Join em SQL se refere a “Inner Join”. Resumindo, um GroupJoin fará um link entre 2 entidades, mesmo que o lado direito do link não tenha nada para vincular. Em contraste, o Join vinculará 2 entidades apenas se ambas as entidades contiverem um link entre elas. ## OrderBy, OrderByDescending ```csharp= class Pet { public string Name { get; set; } public int Age { get; set; } } public static void OrderByEx1() { Pet[] pets = { new Pet { Name="Barley", Age=8 }, new Pet { Name="Boots", Age=4 }, new Pet { Name="Whiskers", Age=1 } }; IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age); foreach (Pet pet in query) { Console.WriteLine("{0} - {1}", pet.Name, pet.Age); } } /* This code produces the following output: Whiskers - 1 Boots - 4 Barley - 8 */ ``` ## ThenBy, ThenByDescending ```csharp= string[] fruits = { "grape", "passionfruit", "banana", "mango", "orange", "raspberry", "apple", "blueberry" }; // Sort the strings first by their length and then //alphabetically by passing the identity selector function. IEnumerable<string> query = fruits.OrderBy(fruit => fruit.Length).ThenBy(fruit => fruit); foreach (string fruit in query) { Console.WriteLine(fruit); } /* This code produces the following output: apple grape mango banana orange blueberry raspberry passionfruit */ ``` - Esse método é implementado usando a execução adiada. O valor de retorno imediato é um objeto que armazena todas as informações necessárias para executar a ação. A consulta representada por esse método **não é executada até que o objeto seja enumerado chamando o GetEnumerator** método diretamente ou usando o foreach no Visual C# ou For Each no Visual Basic. ## Reverse - Ao contrário do OrderBy , esse método de classificação não considera os próprios valores reais para determinar a ordem. Em vez disso, ele apenas retorna os elementos na ordem inversa da qual eles são produzidos pela fonte subjacente. ```csharp= char[] apple = { 'a', 'p', 'p', 'l', 'e' }; char[] reversed = apple.Reverse().ToArray(); foreach (char chr in reversed) { Console.Write(chr + " "); } Console.WriteLine(); /* This code produces the following output: e l p p a */ ``` > https://docs.microsoft.com/pt-br/dotnet/api/system.linq.enumerable.groupjoin?view=net-5.0 > https://patrickdesjardins.com/blog/linq-groupjoin-and-join-differences ## Select O operador Select sempre retorna uma coleção IEnumerable que contém elementos baseados em uma função de transformação. ```csharp= namespace select { public class Produto { public string Nome; public Produto(string nome) { Nome = nome; } } class Program { static void Main(string[] args) { var produtos = new[] { new Produto("MORANGO"), new Produto("LARANJA") }; var resultado = produtos.Select(n => n.Nome.ToLower()); foreach(var nome in resultado) { Console.WriteLine(nome); } } } } ``` ## SelectMany O SelectMany no LINQ é usado para projetar cada elemento de uma sequência para um IEnumerable<T> e, em seguida, achatar as sequências resultantes em uma sequência. Isso significa que o operador SelectMany combina os registros de uma sequência de resultados e, em seguida, converte-o em um resultado. ```csharp= static void Main(string[] args) { string[] frutas = { "Uva", "laranja", "banana" }; int[] numeros = { 1, 2, 3 }; var resultado = frutas.SelectMany(f => numeros, (f, a) => new { Fruta = f, Numero = a }); foreach (var o in resultado) Console.WriteLine(o.Fruta + ", " + o.Numero); } resultado: Uva, 1 Uva, 2 Uva, 3 laranja, 1 laranja, 2 laranja, 3 banana, 1 banana, 2 banana, 3 ``` ### Skip Ele pula o número especificado de elementos em uma coleção ```csharp= static void Main(string[] args) { string[] produtos = { "banana", "pera", "uva", "melancia", "maca", "limao" }; var resultado = produtos.Skip(4); foreach (string produto in resultado) Console.WriteLine(produto); } Resultado: maca limao ``` ### SkipWhile Ele retorna uma nova coleção que inclui todos os elementos restantes uma vez que a condição especificada se torna falsa para qualquer elemento. ```csharp= static void Main(string[] args) { string[] numeros = { "one", "two", "three", "four", "five", "six" }; var resultado = numeros.SkipWhile(w => w.Length == 3); foreach (string numero in resultado) Console.WriteLine(numero); } Resultado: Three Four Five Six ``` ### Take O método de extensão Take() retorna o número especificado de elementos a partir do primeiro elemento. ```csharp= IList<string> lista = new List<string>(){ "One", "Two", "Three", "Four", "Five" }; var novalista = lista.Take(2); foreach(var str in novalista) Console.WriteLine(str); Resultado: One Two ``` ### TakeWhile O método de extensão TakeWhile() retorna os elementos da coleção dada até que a condição especificada seja verdadeira. Se o primeiro elemento em si não satisfaz a condição, então retorna uma coleção vazia. ```csharp= IList<string> strList = new List<string>() { "Three", "Four", "Five", "Hundred" }; var result = strList.TakeWhile(s => s.Length > 4); foreach(string str in result) Console.WriteLine(str); Resultado: Three ``` ## Quantifiers ### All - Determina se todos os elementos de uma sequência atendem a uma condição. - Retorna bool ```csharp= List<int> lista = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; bool pares = lista.All(x => x % 2 == 0); Console.WriteLine(pares); // False ``` ### Any - Determina se qualquer elemento de uma sequência existe ou atende a uma condição - Retorna bool ```csharp= List<int> lista = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; bool temItens = lista.Any(); bool contemNum = lista.Any(x => x == 5); Console.WriteLine(temItens); Console.WriteLine(contemNum); // True // contemNum ``` ### Contains - Determina se uma sequência contém um elemento especificado. - Retorna bool - System.Linq ```csharp= List<int> lista = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; bool contem = lista.Contains(3); Console.WriteLine(contem); // True ``` ## Restriction ### Where - Filtra uma sequência de valores com base num predicado. - Retorna IEnumerable<TSource> ```csharp= List<int> lista = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; List<int> filtro = lista.Where(x => x > 5).ToList(); foreach (int item in filtro) { Console.WriteLine(item); } // { 6, 7, 8, 9, 10 } ``` ## Set ### Distinct - Retorna os elementos distintos de uma sequência usando o comparador de igualdade padrão para comparar valores. - Retorna IEnumerable<TSource> ```csharp= List<int> lista = new List<int> { 1, 2, 3, 3, 5, 7, 4, 5, 6, 7 }; List<int> filtro = lista.Distinct().ToList(); foreach (int item in filtro) { Console.WriteLine(item); } // { 1, 2, 3, 5, 7, 4, 6} ``` ### Except - Produz a diferença de conjunto de duas sequências. - Retorna IEnumerable<TSource> ```csharp= List<int> lista = new List<int> { 1, 2, 3, 5, 7 }; List<int> lista2 = new List<int> { 1, 2}; List<int> filtro = lista.Except(lista2).ToList(); foreach (int item in filtro) { Console.WriteLine(item); } // { 3, 5, 7 } ``` ### Intersect - Produz a interseção de conjunto de duas sequências. - Retorna IEnumerable<TSource> ```csharp= List<int> lista = new List<int> { 1, 2, 3, 5, 7 }; List<int> lista2 = new List<int> { 1, 2 }; List<int> filtro = lista.Intersect(lista2).ToList(); foreach (int item in filtro) { Console.WriteLine(item); } // { 1, 2 } ``` ### Union - Produz a união de conjunto de duas sequências. - Retorna IEnumerable<TSource> ```csharp= List<int> lista = new List<int> { 1, 2, 3, 5, 7 }; List<int> lista2 = new List<int> { 1, 2}; List<int> filtro = lista.Union(lista2).ToList(); foreach (int item in filtro) { Console.WriteLine(item); } // { 1, 2, 3, 5, 7 } ```