Kelompokkan dengan beberapa kolom menggunakan lambda

122

Bagaimana saya bisa mengelompokkan dengan beberapa kolom menggunakan lambda?

Saya melihat contoh bagaimana melakukannya menggunakan LINQ ke entitas, tetapi saya mencari formulir lambda.

Naor
sumber

Jawaban:

252
var query = source.GroupBy(x => new { x.Column1, x.Column2 });
Aducci
sumber
Apakah ini benar-benar berhasil? Saya akan berpikir bahwa uji kesetaraan untuk setiap objek yang Anda kelompokkan akan gagal karena mereka adalah objek dan bukan struct.
Yakub
@Aducci: Terima kasih. Dapatkah Anda memberi contoh bagaimana saya bisa mendapatkan IEnumerable dari item grup?
Naor
6
@Jacob - Jenis anonim adalah kelas yang tidak dapat diubah dengan metode GetHashCode& diganti dengan benar Equals. Mereka dirancang khusus untuk kasus penggunaan semacam ini.
Enigmativity
5
@Naor - GroupBymengembalikan IEnumerable<IGrouping<TKey, TSource>>yang pada dasarnya adalah IEnumerable<IEnumerable<TSource>>dengan Keyproperti di dalam enumerable. Apakah itu membantu Anda mendapatkan "IEnumerable" dari item grup?
Enigmativity
Jika variabel 'sumber' saya adalah Kumpulan Kamus, ini tidak berfungsi. Saran?
Joao Paulo
6

jika meja Anda seperti ini

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")});
Jhankar Mahbub
sumber
6
Sangat penting untuk dicatat bahwa AsEnumerable akan membawa seluruh tabel ke dalam memori sebelum mengelompokkannya. Itu pasti penting di beberapa tabel. Lihat jawaban ini untuk wawasan lebih lanjut: stackoverflow.com/questions/17968469/…
Brandon Barkley
4

Lebih lanjut dari jawaban aduchis di atas - jika Anda kemudian perlu memfilter berdasarkan grup tersebut dengan kunci, Anda dapat menentukan kelas untuk menggabungkan banyak kunci.

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

Di mana CustomerGroupingKey mengambil kunci grup:

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

        public string Country { get; }

        public string Gender { get; }
    }
David McEleney
sumber
1
Mungkin akan menghemat waktu seseorang: lebih baik menggunakan konstruksi default dengan penginisialisasi objek. Pendekatan dalam kode contoh di atas tidak akan diperlakukan dengan baik oleh ORM seperti 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();

        }
    }
Sandeep Tripathi
sumber
1

Saya datang dengan campuran mendefinisikan kelas seperti jawaban David, tetapi tidak membutuhkan kelas Di mana untuk pergi bersamanya. Itu terlihat seperti:

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

Di mana resultRecordsdaftar awal saya yang saya kelompokkan, dan itu a List<ResultCsvImport>. Perhatikan bahwa idenya di sini adalah, saya mengelompokkan menurut 3 kolom, IdObj1 dan IdObj2 dan IdObj3

Jeff Moretti
sumber