Udostępnij za pośrednictwem


Jak: grupy wyników kwerendy (Podręcznik programowania C#)

Grupowanie jest jednym z najbardziej zaawansowanych możliwości LINQ.Następujące przykłady przedstawiają sposób grupowania danych na różne sposoby:

  • Przez jedną właściwość.

  • Według pierwszej litery właściwość ciągu.

  • Według obliczanej zakresu numeryczne.

  • Predykat logiczną lub inne wyrażenia.

  • Według klucza złożonego.

Ponadto dwóch ostatnich kwerend ich rezultaty projektu do nowego typu anonimowy, który zawiera tylko student imienia i nazwiska.Aby uzyskać więcej informacji, zobacz Klauzula grupy (C# odniesienia).

Przykład

We wszystkich przykładach w tym temacie, użyj następujących źródeł klas i danych pomocnika.

public class StudentClass
{
    #region data
    protected enum GradeLevel { FirstYear = 1, SecondYear, ThirdYear, FourthYear };
    protected class Student
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int ID { get; set; }
        public GradeLevel Year;
        public List<int> ExamScores;
    }

    protected static List<Student> students = new List<Student>
    {
        new Student {FirstName = "Terry", LastName = "Adams", ID = 120, 
            Year = GradeLevel.SecondYear, 
            ExamScores = new List<int>{ 99, 82, 81, 79}},
        new Student {FirstName = "Fadi", LastName = "Fakhouri", ID = 116, 
            Year = GradeLevel.ThirdYear,
            ExamScores = new List<int>{ 99, 86, 90, 94}},
        new Student {FirstName = "Hanying", LastName = "Feng", ID = 117, 
            Year = GradeLevel.FirstYear, 
            ExamScores = new List<int>{ 93, 92, 80, 87}},
        new Student {FirstName = "Cesar", LastName = "Garcia", ID = 114, 
            Year = GradeLevel.FourthYear,
            ExamScores = new List<int>{ 97, 89, 85, 82}},
        new Student {FirstName = "Debra", LastName = "Garcia", ID = 115, 
            Year = GradeLevel.ThirdYear, 
            ExamScores = new List<int>{ 35, 72, 91, 70}},
        new Student {FirstName = "Hugo", LastName = "Garcia", ID = 118, 
            Year = GradeLevel.SecondYear, 
            ExamScores = new List<int>{ 92, 90, 83, 78}},
        new Student {FirstName = "Sven", LastName = "Mortensen", ID = 113, 
            Year = GradeLevel.FirstYear, 
            ExamScores = new List<int>{ 88, 94, 65, 91}},
        new Student {FirstName = "Claire", LastName = "O'Donnell", ID = 112, 
            Year = GradeLevel.FourthYear, 
            ExamScores = new List<int>{ 75, 84, 91, 39}},
        new Student {FirstName = "Svetlana", LastName = "Omelchenko", ID = 111, 
            Year = GradeLevel.SecondYear, 
            ExamScores = new List<int>{ 97, 92, 81, 60}},
        new Student {FirstName = "Lance", LastName = "Tucker", ID = 119, 
            Year = GradeLevel.ThirdYear, 
            ExamScores = new List<int>{ 68, 79, 88, 92}},
        new Student {FirstName = "Michael", LastName = "Tucker", ID = 122, 
            Year = GradeLevel.FirstYear, 
            ExamScores = new List<int>{ 94, 92, 91, 91}},
        new Student {FirstName = "Eugene", LastName = "Zabokritski", ID = 121,
            Year = GradeLevel.FourthYear, 
            ExamScores = new List<int>{ 96, 85, 91, 60}}
    };
    #endregion

    //Helper method, used in GroupByRange.
    protected static int GetPercentile(Student s)
    {
        double avg = s.ExamScores.Average();
        return avg > 0 ? (int)avg / 10 : 0;
    }



    public void QueryHighScores(int exam, int score)
    {
        var highScores = from student in students
                         where student.ExamScores[exam] > score
                         select new {Name = student.FirstName, Score = student.ExamScores[exam]};

        foreach (var item in highScores)
        {
            Console.WriteLine("{0,-15}{1}", item.Name, item.Score);
        }
    }
}

public class Program
{
    public static void Main()
    {
        StudentClass sc = new StudentClass();
        sc.QueryHighScores(1, 90);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit");
        Console.ReadKey();
    }
}

Poniższy przykład pokazuje sposób grupowania elementów źródła przy użyciu pojedynczej właściwości elementu jako klucz grupy.W tym przypadku jest klucz string, nazwisko Studenta.Istnieje również możliwość użycia podciągu dla klucza.Operacja grupowania używa domyślnego modułu porównującego równości dla danego typu.

Wklej następujące metody do StudentClass klasy.Zmienić instrukcję wywołującego w Main metoda sc.GroupBySingleProperty().

public void GroupBySingleProperty()
{
    Console.WriteLine("Group by a single property in an object:");

    // Variable queryLastNames is an IEnumerable<IGrouping<string, 
    // DataClass.Student>>. 
    var queryLastNames =
        from student in students
        group student by student.LastName into newGroup
        orderby newGroup.Key
        select newGroup;

    foreach (var nameGroup in queryLastNames)
    {
        Console.WriteLine("Key: {0}", nameGroup.Key);
        foreach (var student in nameGroup)
        {
            Console.WriteLine("\t{0}, {1}", student.LastName, student.FirstName);
        }
    }
}
/* Output:
    Group by a single property in an object:
    Key: Adams
            Adams, Terry
    Key: Fakhouri
            Fakhouri, Fadi
    Key: Feng
            Feng, Hanying
    Key: Garcia
            Garcia, Cesar
            Garcia, Debra
            Garcia, Hugo
    Key: Mortensen
            Mortensen, Sven
    Key: O'Donnell
            O'Donnell, Claire
    Key: Omelchenko
            Omelchenko, Svetlana
    Key: Tucker
            Tucker, Lance
            Tucker, Michael
    Key: Zabokritski
            Zabokritski, Eugene
*/

Poniższy przykład pokazuje sposób grupowania elementów źródła przy użyciu coś innego niż właściwość obiektu dla klucza grupy.W tym przykładzie klucz jest pierwszej litery nazwy ostatniego Studenta.

Wklej następujące metody do StudentClass klasy.Zmienić instrukcję wywołującego w Main metoda sc.GroupBySubstring().

public void GroupBySubstring()
{            
    Console.WriteLine("\r\nGroup by something other than a property of the object:");

    var queryFirstLetters =
        from student in students
        group student by student.LastName[0];

    foreach (var studentGroup in queryFirstLetters)
    {
        Console.WriteLine("Key: {0}", studentGroup.Key);
        // Nested foreach is required to access group items.
        foreach (var student in studentGroup)
        {
            Console.WriteLine("\t{0}, {1}", student.LastName, student.FirstName);
        }
    }           
}
/* Output:
    Group by something other than a property of the object:
    Key: A
            Adams, Terry
    Key: F
            Fakhouri, Fadi
            Feng, Hanying
    Key: G
            Garcia, Cesar
            Garcia, Debra
            Garcia, Hugo
    Key: M
            Mortensen, Sven
    Key: O
            O'Donnell, Claire
            Omelchenko, Svetlana
    Key: T
            Tucker, Lance
            Tucker, Michael
    Key: Z
            Zabokritski, Eugene
*/

Poniższy przykład pokazuje sposób grupowania elementów źródła przy użyciu zakres liczbowy jako klucz grupy.Kwerenda projektów następnie wyniki na typ anonimowy, zawierający tylko imię i nazwisko oraz zakres percentyl, do której należy dany student.Typ anonimowy jest używana, ponieważ nie jest konieczne użycie z pełną Student obiekt, aby wyświetlić wyniki.GetPercentileFunkcja helper, służącą do obliczania wartości percentylu jest oparty na średni wynik Studenta.Metoda zwraca liczbę całkowitą od 0 do 10.

//Helper method, used in GroupByRange.
protected static int GetPercentile(Student s)
{
    double avg = s.ExamScores.Average();
    return avg > 0 ? (int)avg / 10 : 0;
}

Wklej następujące metody do StudentClass klasy.Zmienić instrukcję wywołującego w Main metoda sc.GroupByRange().

public void GroupByRange()
{            
    Console.WriteLine("\r\nGroup by numeric range and project into a new anonymous type:");

    var queryNumericRange =
        from student in students
        let percentile = GetPercentile(student)
        group new { student.FirstName, student.LastName } by percentile into percentGroup
        orderby percentGroup.Key
        select percentGroup;

    // Nested foreach required to iterate over groups and group items.
    foreach (var studentGroup in queryNumericRange)
    {
        Console.WriteLine("Key: {0}", (studentGroup.Key * 10));
        foreach (var item in studentGroup)
        {
            Console.WriteLine("\t{0}, {1}", item.LastName, item.FirstName);
        }
    }            
}
/* Output:
    Group by numeric range and project into a new anonymous type:
    Key: 60
            Garcia, Debra
    Key: 70
            O'Donnell, Claire
    Key: 80
            Adams, Terry
            Feng, Hanying
            Garcia, Cesar
            Garcia, Hugo
            Mortensen, Sven
            Omelchenko, Svetlana
            Tucker, Lance
            Zabokritski, Eugene
    Key: 90
            Fakhouri, Fadi
            Tucker, Michael
*/

Poniższy przykład pokazuje sposób grupowania elementów źródła przy użyciu wyrażeń logicznych porównania.W tym przykładzie wyrażenie logiczne sprawdza, czy wynik egzaminu średnia studenta jest większa niż 75.Jak w poprzednich przykładach wyniki są rzucie na typ anonimowy, ponieważ element kompletne źródło nie jest potrzebne.Należy zauważyć, że właściwości w polu Typ anonimowy stają się właściwości na Key Członkowskich i będą dostępne przez nazwę, gdy kwerenda jest wykonywana.

Wklej następujące metody do StudentClass klasy.Zmienić instrukcję wywołującego w Main metoda sc.GroupByBoolean().

public void GroupByBoolean()
{            
    Console.WriteLine("\r\nGroup by a Boolean into two groups with string keys");
    Console.WriteLine("\"True\" and \"False\" and project into a new anonymous type:");
    var queryGroupByAverages = from student in students
                               group new { student.FirstName, student.LastName }
                                    by student.ExamScores.Average() > 75 into studentGroup
                               select studentGroup;

    foreach (var studentGroup in queryGroupByAverages)
    {
        Console.WriteLine("Key: {0}", studentGroup.Key);
        foreach (var student in studentGroup)
            Console.WriteLine("\t{0} {1}", student.FirstName, student.LastName);
    }            
}
/* Output:
    Group by a Boolean into two groups with string keys
    "True" and "False" and project into a new anonymous type:
    Key: True
            Terry Adams
            Fadi Fakhouri
            Hanying Feng
            Cesar Garcia
            Hugo Garcia
            Sven Mortensen
            Svetlana Omelchenko
            Lance Tucker
            Michael Tucker
            Eugene Zabokritski
    Key: False
            Debra Garcia
            Claire O'Donnell
*/

Poniższy przykład pokazuje sposób użycia typ anonimowy do hermetyzacji klucz, który zawiera wiele wartości.W tym przykładzie pierwsza wartość klucza jest pierwszej litery nazwy ostatniego Studenta.Druga wartość klucza jest wartością logiczną, która określa, czy student zdobył ponad 85 na pierwszym egzaminu.Grupy można zamówić w dowolnej właściwości w kluczu.

Wklej następujące metody do StudentClass klasy.Zmienić instrukcję wywołującego w Main metoda sc.GroupByCompositeKey().

public void GroupByCompositeKey()
{

    var queryHighScoreGroups =
        from student in students
        group student by new { FirstLetter = student.LastName[0], 
            Score = student.ExamScores[0] > 85 } into studentGroup
        orderby studentGroup.Key.FirstLetter
        select studentGroup;

    Console.WriteLine("\r\nGroup and order by a compound key:");
    foreach (var scoreGroup in queryHighScoreGroups)
    {
        string s = scoreGroup.Key.Score == true ? "more than" : "less than";
        Console.WriteLine("Name starts with {0} who scored {1} 85", scoreGroup.Key.FirstLetter, s);
        foreach (var item in scoreGroup)
        {
            Console.WriteLine("\t{0} {1}", item.FirstName, item.LastName);
        }
    }
}
/* Output:
    Group and order by a compound key:
    Name starts with A who scored more than 85
            Terry Adams
    Name starts with F who scored more than 85
            Fadi Fakhouri
            Hanying Feng
    Name starts with G who scored more than 85
            Cesar Garcia
            Hugo Garcia
    Name starts with G who scored less than 85
            Debra Garcia
    Name starts with M who scored more than 85
            Sven Mortensen
    Name starts with O who scored less than 85
            Claire O'Donnell
    Name starts with O who scored more than 85
            Svetlana Omelchenko
    Name starts with T who scored less than 85
            Lance Tucker
    Name starts with T who scored more than 85
            Michael Tucker
    Name starts with Z who scored more than 85
            Eugene Zabokritski
*/

Kompilowanie kodu

Kopiowanie i wklejanie każdej metody, która ma być testowana w StudentClass klasy.Dodać instrukcję wywołania metody do Main metody i naciśnij klawisz F5.

Jeśli te metody dostosowania się do własnej aplikacji, należy pamiętać, że LINQ wymaga wersji 3.5 lub 4 .NET Framework, i że projekt musi zawierać odniesienie do System.Core.dll i za pomocą dyrektywy dla System.Linq.LINQ SQL, LINQ XML i LINQ DataSet typów wymagają dodatkowych za pomocą dyrektyw i odwołania.Aby uzyskać więcej informacji, zobacz Jak: Tworzenie projektu LINQ.

Zobacz też

Zadania

Jak: wykonywanie podkwerendy w operacji grupowania (Podręcznik programowania C#)

Jak: Tworzenie grupy zagnieżdżone (Podręcznik programowania C#)

Informacje

Klauzula grupy (C# odniesienia)

Typy anonimowe (Podręcznik programowania C#)

GroupBy

IGrouping<TKey, TElement>

Koncepcje

Wyrażenia w kwerendzie LINQ (Podręcznik programowania C#)

Grupowanie danych