람다를 사용하여 여러 열로 그룹화


122

람다를 사용하여 여러 열로 그룹화하려면 어떻게해야합니까?

엔티티에 linq를 사용하는 방법에 대한 예제를 보았지만 람다 형식을 찾고 있습니다.

답변:


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

이것이 실제로 작동할까요? 그룹화하는 각 개체에 대한 동등성 테스트는 구조체가 아니라 개체이기 때문에 실패 할 것이라고 생각합니다.
야곱

@Aducci : 감사합니다. 그룹 항목의 IEnumerable을 어떻게 얻을 수 있습니까?
Naor

6
@Jacob-익명 유형은 적절하게 재정의 된 GetHashCode& Equals메소드 가있는 불변 클래스입니다 . 정확히 이런 종류의 사용 사례를 위해 설계되었습니다.
Enigmativity 2011-08-04

5
@Naor - GroupBy반환 IEnumerable<IGrouping<TKey, TSource>>본질적이다 IEnumerable<IEnumerable<TSource>>Key내부 열거에 속성을. 그룹 항목의 "IEnumerable"을 얻는 데 도움이됩니까?
Enigmativity 2011 년

내 '소스'변수가 사전 컬렉션이면 작동하지 않습니다. 제안?
Joao Paulo

6

당신의 테이블이 이러면

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")});

6
AsEnumerable은 그룹화하기 전에 전체 테이블을 메모리로 가져옵니다. 일부 테이블에서는 확실히 중요합니다. 자세한 내용은 다음 답변을 참조하십시오. stackoverflow.com/questions/17968469/…
Brandon Barkley

4

또한에 aduchis 위의 대답 - 당신이 다음 키에 의해 그 그룹에 따라 필터를 필요로하는 경우, 당신은 많은 키를 래핑하는 클래스를 정의 할 수 있습니다.

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

CustomerGroupingKey가 그룹 키를 사용하는 경우 :

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

        public string Country { get; }

        public string Gender { get; }
    }

1
아마도 누군가의 시간을 절약 할 수있을 것입니다. 객체 초기화 자와 함께 기본 구조를 사용하는 것이 좋습니다. 위 샘플 코드의 접근 방식은 EF Core와 같은 ORM에서 잘 처리 되지 않습니다 .
Konstantin

2
     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();

        }
    }

1

나는 David의 대답과 같은 클래스를 정의하는 혼합을 생각해 냈지만 Where 클래스가 필요하지 않았습니다. 다음과 같이 보입니다.

var resultsGroupings = resultsRecords.GroupBy(r => new { r.IdObj1, r.IdObj2, r.IdObj3})
                                    .Select(r => new ResultGrouping {
                                        IdObj1= r.Key.IdObj1,
                                        IdObj2= r.Key.IdObj2,
                                        IdObj3= r.Key.IdObj3,
                                        Results = r.ToArray(),
                                        Count = r.Count()
                                    });



private class ResultGrouping
        {
            public short IdObj1{ get; set; }
            public short IdObj2{ get; set; }
            public int IdObj3{ get; set; }

            public ResultCsvImport[] Results { get; set; }
            public int Count { get; set; }
        }

resultRecords내가 그룹화하는 초기 목록은 어디에 있습니까 List<ResultCsvImport>? 여기에 대한 아이디어는 IdObj1 및 IdObj2 및 IdObj3의 3 개 열로 그룹화된다는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.