Pertanyaan Kelompokkan di LINQ


Anggaplah jika kita memiliki kelas seperti

class Person { 
    internal int PersonID; 
    internal string car  ; 
}

Sekarang saya memiliki daftar kelas ini: List<Person> persons;

Sekarang daftar ini dapat memiliki beberapa instance dengan PersonID yang sama, misalnya:

persons[0] = new Person { PersonID = 1, car = "Ferrari" }; 
persons[1] = new Person { PersonID = 1, car = "BMW"     }; 
persons[2] = new Person { PersonID = 2, car = "Audi"    }; 

Apakah ada cara saya dapat mengelompokkannya personID dan dapatkan daftar semua mobil yang dia miliki?

Misalnya, hasil yang diharapkan

class Result { 
   int PersonID;
   List<string> cars; 
}

Jadi setelah pengelompokan, saya akan mendapatkan:

results[0].PersonID = 1; 
List<string> cars = results[0].cars; 

result[1].PersonID = 2; 
List<string> cars = result[1].cars;

Dari apa yang telah saya lakukan sejauh ini:

var results = from p in persons
              group p by p.PersonID into g
              select new { PersonID = g.Key, // this is where I am not sure what to do

Bisakah seseorang mengarahkan saya ke arah yang benar?


806
2017-09-06 19:44


asal


Jawaban:


Benar-benar - pada dasarnya Anda menginginkan:

var results = from p in persons
              group p.car by p.PersonId into g
              select new { PersonId = g.Key, Cars = g.ToList() };

Atau sebagai ekspresi non-query:

var results = persons.GroupBy(
    p => p.PersonId, 
    p => p.car,
    (key, g) => new { PersonId = key, Cars = g.ToList() });

Pada dasarnya isi grup (saat melihat sebagai IEnumerable<T>) adalah urutan nilai apa pun yang ada dalam proyeksi (p.car dalam hal ini) hadir untuk kunci yang diberikan.

Untuk lebih lanjut tentang caranya GroupBy bekerja, lihat saya Edulinq memposting topik ini.

(Saya telah mengganti namanya PersonID untuk PersonId di atas, untuk mengikuti Konvensi penamaan NET.)

Atau, Anda bisa menggunakan Lookup:

var carsByPersonId = persons.ToLookup(p => p.PersonId, p => p.car);

Anda kemudian bisa mendapatkan mobil untuk setiap orang dengan sangat mudah:

// This will be an empty sequence for any personId not in the lookup
var carsForPerson = carsByPersonId[personId];

1365
2017-09-06 19:46



var results = from p in persons
              group p by p.PersonID into g
              select new { PersonID = g.Key,
                           /**/car = g.Select(g=>g.car).FirstOrDefault()/**/}

44
2018-02-05 17:25



var results = from p in persons
              group p by p.PersonID into g
              select new { PersonID = g.Key, Cars = g.Select(m => m.car) };

28
2017-08-18 10:26



Anda juga dapat Coba ini.

var results= persons.GroupBy(n => new { n.PersonId, n.car})
                .Select(g => new {
                               g.Key.PersonId,
                               g.Key.car)}).ToList();

23
2017-12-02 06:15



mencoba

persons.GroupBy(x => x.PersonId).Select(x => x)

atau

untuk memeriksa apakah ada orang yang mengulang dalam daftar Anda coba

persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x)

12
2017-08-15 22:24



Saya telah membuat sampel kode kerja dengan Sintaks Permintaan dan Sintaks Metode. Saya harap itu membantu yang lain :)

Anda juga dapat menjalankan kode di .Net Fiddle di sini:

using System;
using System.Linq;
using System.Collections.Generic;

class Person
{ 
    public int PersonId; 
    public string car  ; 
}

class Result
{ 
   public int PersonId;
   public List<string> Cars; 
}

public class Program
{
    public static void Main()
    {
        List<Person> persons = new List<Person>()
        {
            new Person { PersonId = 1, car = "Ferrari" },
            new Person { PersonId = 1, car = "BMW" },
            new Person { PersonId = 2, car = "Audi"}
        };

        //With Query Syntax

        List<Result> results1 = (
            from p in persons
            group p by p.PersonId into g
            select new Result()
                {
                    PersonId = g.Key, 
                    Cars = g.Select(c => c.car).ToList()
                }
            ).ToList();

        foreach (Result item in results1)
        {
            Console.WriteLine(item.PersonId);
            foreach(string car in item.Cars)
            {
                Console.WriteLine(car);
            }
        }

        Console.WriteLine("-----------");

        //Method Syntax

        List<Result> results2 = persons
            .GroupBy(p => p.PersonId, 
                     (k, c) => new Result()
                             {
                                 PersonId = k,
                                 Cars = c.Select(cs => cs.car).ToList()
                             }
                    ).ToList();

        foreach (Result item in results2)
        {
            Console.WriteLine(item.PersonId);
            foreach(string car in item.Cars)
            {
                Console.WriteLine(car);
            }
        }
    }
}

Inilah hasilnya:

1
Ferrari
BMW
2
Audi
-----------
1
Ferrari
BMW
2
Audi


6
2017-11-30 19:12



Coba ini :

var results= persons.GroupBy(n => n.PersonId)
            .Select(g => new {
                           PersonId=g.Key,
                           Cars=g.Select(p=>p.car).ToList())}).ToList();

Tetapi kinerja-bijaksana praktik berikut ini lebih baik dan lebih dioptimalkan dalam penggunaan memori (ketika array kami berisi lebih banyak item seperti jutaan):

var carDic=new Dictionary<int,List<string>>();
for(int i=0;i<persons.length;i++)
{
   var person=persons[i];
   if(carDic.ContainsKey(person.PersonId))
   {
        carDic[person.PersonId].Add(person.car);
   }
   else
   {
        carDic[person.PersonId]=new List<string>(){person.car};
   }
}
//returns the list of cars for PersonId 1
var carList=carDic[1];

2
2018-05-26 05:51