2011-08-04 30 views
75

¿Cómo puedo agruparme con varias columnas usando lambda?Agrupar por varias columnas usando lambda

Vi ejemplos de cómo hacerlo usando linq para entidades, pero estoy buscando la forma lambda.

+0

No Te tiene una consulta específica en mente? –

Respuesta

150
var query = source.GroupBy(x => new { x.Column1, x.Column2 }); 
+0

¿Esto realmente funcionaría? Creo que la prueba de igualdad para cada objeto que está agrupando fallaría, ya que son objetos y no estructuras. – Jacob

+0

@Aducci: Gracias. ¿Puedes dar un ejemplo de cómo puedo obtener IEnumerable de los elementos del grupo? – Naor

+4

@Jacob: los tipos anónimos son clases inmutables con los métodos 'GetHashCode' y' Equals' correctamente anulados. Fueron diseñados para este tipo de casos de uso. – Enigmativity

8

si la tabla es así

rowId  col1 col2 col3 col4 
1   a  e  12  2 
2   b  f  42  5 
3   a  e  32  2 
4   b  f  44  5 


var grouped = myTable.AsEnumerable().GroupBy(r=> new {pp1 = r.Field<int>("col1"), pp2 = r.Field<int>("col2")}); 
2

Además de aduchis respuesta anterior - si este caso es necesario filtrar en función de los grupos de teclas, se puede definir una clase para envolver las muchas claves.

return customers.GroupBy(a => new CustomerGroupingKey(a.Country, a.Gender)) 
       .Where(a => a.Key.Country == "Ireland" && a.Key.Gender == "M") 
       .SelectMany(a => a) 
       .ToList(); 

Dónde CustomerGroupingKey toma las claves de grupo:

private class CustomerGroupingKey 
    { 
     public CustomerGroupingKey(string country, string gender) 
     { 
      Country = country; 
      Gender = gender; 
     } 

     public string Country { get; } 

     public string Gender { get; } 
    } 
+0

Probablemente le ahorrará a alguien algo de tiempo: es mejor usar construcciones predeterminadas con inicializadores de objetos. El enfoque en el código de ejemplo anterior ** ** no será tratado por ORM como EF Core well. – Konstantin

0
 class Element 
     { 
      public string Company;   
      public string TypeOfInvestment; 
      public decimal Worth; 
     } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
     List<Element> elements = new List<Element>() 
      { 
       new Element { Company = "JPMORGAN CHASE",TypeOfInvestment = "Stocks", Worth = 96983 }, 
       new Element { Company = "AMER TOWER CORP",TypeOfInvestment = "Securities", Worth = 17141 }, 
       new Element { Company = "ORACLE CORP",TypeOfInvestment = "Assets", Worth = 59372 }, 
       new Element { Company = "PEPSICO INC",TypeOfInvestment = "Assets", Worth = 26516 }, 
       new Element { Company = "PROCTER & GAMBL",TypeOfInvestment = "Stocks", Worth = 387050 }, 
       new Element { Company = "QUASLCOMM INC",TypeOfInvestment = "Bonds", Worth = 196811 }, 
       new Element { Company = "UTD TECHS CORP",TypeOfInvestment = "Bonds", Worth = 257429 }, 
       new Element { Company = "WELLS FARGO-NEW",TypeOfInvestment = "Bank Account", Worth = 106600 }, 
       new Element { Company = "FEDEX CORP",TypeOfInvestment = "Stocks", Worth = 103955 }, 
       new Element { Company = "CVS CAREMARK CP",TypeOfInvestment = "Securities", Worth = 171048 }, 
      }; 

      //Group by on multiple column in LINQ (Query Method) 
      var query = from e in elements 
         group e by new{e.TypeOfInvestment,e.Company} into eg 
         select new {eg.Key.TypeOfInvestment, eg.Key.Company, Points = eg.Sum(rl => rl.Worth)}; 



      foreach (var item in query) 
      { 
       Console.WriteLine(item.TypeOfInvestment.PadRight(20) + " " + item.Points.ToString()); 
      } 


      //Group by on multiple column in LINQ (Lambda Method) 
      var CompanyDetails =elements.GroupBy(s => new { s.Company, s.TypeOfInvestment}) 
           .Select(g => 
              new 
              { 
               company = g.Key.Company, 
               TypeOfInvestment = g.Key.TypeOfInvestment,    
               Balance = g.Sum(x => Math.Round(Convert.ToDecimal(x.Worth), 2)), 
              } 
            ); 
      foreach (var item in CompanyDetails) 
      { 
       Console.WriteLine(item.TypeOfInvestment.PadRight(20) + " " + item.Balance.ToString()); 
      } 
      Console.ReadLine(); 

     } 
    }