Nhóm theo nhiều cột bằng lambda


122

Làm cách nào để tôi có thể nhóm theo nhiều cột bằng lambda?

Tôi đã xem các ví dụ về cách thực hiện bằng cách sử dụng linq cho các thực thể, nhưng tôi đang tìm kiếm biểu mẫu lambda.

Câu trả lời:


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

Điều này có thực sự hoạt động không? Tôi nghĩ rằng bài kiểm tra bình đẳng cho từng đối tượng mà bạn đang nhóm sẽ thất bại vì chúng là đối tượng chứ không phải cấu trúc.
Jacob

@Aducci: Cảm ơn. Bạn có thể ví dụ làm thế nào tôi có thể lấy IEnumerable của các mục nhóm?
Naor

6
@Jacob - Các kiểu ẩn danh là các lớp bất biến với các phương thức GetHashCode& Equalsphương thức được ghi đè đúng cách . Họ đã thiết kế chính xác loại trường hợp sử dụng này.
Enigmativity

5
@Naor - GroupBytrả về một về IEnumerable<IGrouping<TKey, TSource>>cơ bản là một IEnumerable<IEnumerable<TSource>>với một thuộc Keytính ở bên trong có thể liệt kê. Điều đó có giúp bạn nhận được "IEnumerable" của các mục trong nhóm không?
Enigmativity

Nếu biến 'nguồn' của tôi là Bộ sưu tập từ điển, điều này không hoạt động. Gợi ý?
Joao Paulo

6

nếu bàn của bạn như thế này

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
Điều rất quan trọng cần lưu ý là AsEnumerable sẽ đưa toàn bộ bảng vào bộ nhớ trước khi nhóm nó. Điều đó chắc chắn quan trọng trên một số bảng. Xem câu trả lời này để biết thêm thông tin chi tiết: stackoverflow.com/questions/17968469/…
Brandon Barkley,

4

Hơn nữa để aduchis câu trả lời ở trên - nếu sau đó bạn cần phải lọc dựa trên những nhóm bằng các phím, bạn có thể định nghĩa một lớp học để quấn các phím nhiều.

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

Nơi CustomerGroupingKey lấy các khóa nhóm:

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

        public string Country { get; }

        public string Gender { get; }
    }

1
Có thể sẽ giúp ai đó tiết kiệm thời gian: tốt hơn là sử dụng các cấu trúc mặc định với các bộ khởi tạo đối tượng. Cách tiếp cận trong mã mẫu ở trên sẽ không được ORMs xử lý tốt như EF Core.
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

Tôi đã nghĩ ra sự kết hợp giữa việc xác định một lớp học như câu trả lời của David, nhưng không yêu cầu lớp học Đi cùng với nó. Nó trông giống như sau:

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

Trường hợp resultRecordslà danh sách ban đầu của tôi, tôi đang nhóm, và một của nó List<ResultCsvImport>. Lưu ý rằng ý tưởng ở đây là, tôi đang nhóm theo 3 cột, IdObj1 và IdObj2 và IdObj3

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.