Group by in LINQ

后端 未结 10 1626
悲哀的现实
悲哀的现实 2020-11-21 06:58

Let\'s suppose if we have a class like:

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

I have a list of this class

相关标签:
10条回答
  • 2020-11-21 07:11
    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()/**/}
    
    0 讨论(0)
  • 2020-11-21 07:17

    I have created a working code sample with Query Syntax and Method Syntax. I hope it helps the others :)

    You can also run the code on .Net Fiddle here:

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

    Here is the result:

    1
    Ferrari
    BMW
    2
    Audi
    -----------
    1
    Ferrari
    BMW
    2
    Audi
    
    
    0 讨论(0)
  • 2020-11-21 07:21

    Absolutely - you basically want:

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

    Or as a non-query expression:

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

    Basically the contents of the group (when viewed as an IEnumerable<T>) is a sequence of whatever values were in the projection (p.car in this case) present for the given key.

    For more on how GroupBy works, see my Edulinq post on the topic.

    (I've renamed PersonID to PersonId in the above, to follow .NET naming conventions.)

    Alternatively, you could use a Lookup:

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

    You can then get the cars for each person very easily:

    // This will be an empty sequence for any personId not in the lookup
    var carsForPerson = carsByPersonId[personId];
    
    0 讨论(0)
  • 2020-11-21 07:28
    var results = from p in persons
                  group p by p.PersonID into g
                  select new { PersonID = g.Key, Cars = g.Select(m => m.car) };
    
    0 讨论(0)
  • 2020-11-21 07:28

    try

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

    or

    to check if any person is repeating in your list try

    persons.GroupBy(x => x.PersonId).Where(x => x.Count() > 1).Any(x => x)
    
    0 讨论(0)
  • 2020-11-21 07:29

    The following example uses the GroupBy method to return objects that are grouped by PersonID.

    var results = persons.GroupBy(x => x.PersonID)
                  .Select(x => (PersonID: x.Key, Cars: x.Select(p => p.car).ToList())
                  ).ToList();
    

    Or

     var results = persons.GroupBy(
                   person => person.PersonID,
                   (key, groupPerson) => (PersonID: key, Cars: groupPerson.Select(x => x.car).ToList()));
    

    Or

     var results = from person in persons
                   group person by person.PersonID into groupPerson
                   select (PersonID: groupPerson.Key, Cars: groupPerson.Select(x => x.car).ToList());
    

    Or you can use ToLookup, Basically ToLookup uses EqualityComparer<TKey>.Default to compare keys and do what you should do manually when using group by and to dictionary. i think it's excuted inmemory

     ILookup<int, string> results = persons.ToLookup(
                person => person.PersonID,
                person => person.car);
    
    0 讨论(0)
提交回复
热议问题