Udostępnij za pośrednictwem


group — Klauzula (odwołanie w C#)

group Klauzuli zwraca ciąg IGrouping obiektów, które zawierają zera lub więcej elementów, które pasują do wartości klucza dla grupy.Na przykład można grupować sekwencji ciągi w pierwszej litery każdego ciągu.W tym przypadku pierwsza litera jest kluczem i ma typ chari jest przechowywany w Key właściwości każdego IGrouping obiektu.Typ klucza jest ustalany przez kompilator.

Można zakończyć w wyrażeniu kwerendy z group klauzuli, jak pokazano w następującym przykładzie:

// Query variable is an IEnumerable<IGrouping<char, Student>> 
var studentQuery1 =
    from student in students
    group student by student.Last[0];

Jeśli chcesz wykonywać operacje dodatkowych kwerend na każdej grupy można określić identyfikator tymczasowych przy użyciu do kontekstowe słowa kluczowego.Kiedy używać into, musi kontynuować kwerendy i ostatecznie zakończyć z albo select instrukcji lub w innym group klauzuli, jak pokazano w poniższym fragmencie:

// Group students by the first letter of their last name 
// Query variable is an IEnumerable<IGrouping<char, Student>> 
var studentQuery2 =
    from student in students
    group student by student.Last[0] into g
    orderby g.Key
    select g;

Zakończenie więcej przykładów użycia group z i bez into są podane w sekcji przykład tego tematu.

Wyliczanie wyników kwerendy grupy

Ponieważ IGrouping przedmioty produkowane przez group kwerendy są zasadniczo lista listy, należy użyć zagnieżdżonych foreach pętli, dostęp do elementów w każdej grupie.Zewnętrzna pętla wykonuje iterację przez klucze grup i wewnętrzna pętla wykonuje iterację przez każdego elementu w samej grupy.Grupa może mieć kluczem, ale nie elementy.Oto foreach pętli, który wykonuje kwerendę w poprzednich przykładach kodu:

// Iterate group items with a nested foreach. This IGrouping encapsulates 
// a sequence of Student objects, and a Key of type char. 
// For convenience, var can also be used in the foreach statement. 
foreach (IGrouping<char, Student> studentGroup in studentQuery2)
{
     Console.WriteLine(studentGroup.Key);
     // Explicit type for student could also be used here. 
     foreach (var student in studentGroup)
     {
         Console.WriteLine("   {0}, {1}", student.Last, student.First);
     }
 }

Typy kluczy

Klucze grup mogą być dowolnego typu, takie jak ciąg znaków, typu liczbowego wbudowanych lub przez użytkownika o nazwie typu lub anonimowe.

Grupowanie według ciąg

Poprzednie przykłady kodu używany char.Ciągu klucza może łatwo zostały określone zamiast tego, na przykład pełne nazwisko:

// Same as previous example except we use the entire last name as a key. 
// Query variable is an IEnumerable<IGrouping<string, Student>> 
 var studentQuery3 =
     from student in students
     group student by student.Last;

Grupowanie według bool

W poniższym przykładzie pokazano sposób użycia wartość bool klucza podzielić na dwie grupy wyników.Należy zauważyć, że wartość jest produkowany przez wyrażenia podrzędnego w group klauzuli.

class GroupSample1
{
    // The element type of the data source. 
    public class Student
    {
        public string First { get; set; }
        public string Last { get; set; }
        public int ID { get; set; }
        public List<int> Scores;
    }

    public static List<Student> GetStudents()
    {
        // Use a collection initializer to create the data source. Note that each element 
        //  in the list contains an inner sequence of scores.
        List<Student> students = new List<Student>
        {
           new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 72, 81, 60}},
           new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
           new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int> {99, 89, 91, 95}},
           new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int> {72, 81, 65, 84}},
           new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {97, 89, 85, 82}} 
        };

        return students;

    }

    static void Main()
    {
        // Obtain the data source.
        List<Student> students = GetStudents();

        // Group by true or false. 
        // Query variable is an IEnumerable<IGrouping<bool, Student>> 
        var booleanGroupQuery =
            from student in students
            group student by student.Scores.Average() >= 80; //pass or fail! 

        // Execute the query and access items in each group 
        foreach (var studentGroup in booleanGroupQuery)
        {
            Console.WriteLine(studentGroup.Key == true ? "High averages" : "Low averages");
            foreach (var student in studentGroup)
            {
                Console.WriteLine("   {0}, {1}:{2}", student.Last, student.First, student.Scores.Average());
            }
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
  Low averages
   Omelchenko, Svetlana:77.5
   O'Donnell, Claire:72.25
   Garcia, Cesar:75.5
  High averages
   Mortensen, Sven:93.5
   Garcia, Debra:88.25
*/

Grupowanie według zakresu numeryczne

W następnym przykładzie użyto wyrażenia do tworzenia kluczy numerycznych grupy, które reprezentuje zakres wartości percentylu.Uwaga Użycie Niech jako wygodną lokalizacją do przechowywania metody wywołania wynik, tak, aby nie trzeba wywołać metodę dwa razy w group klauzuli.Należy zwrócić uwagę, również w group klauzulę, że aby uniknąć wyjątek "dzielenie przez zero" kod sprawdza upewnić się, że uczeń nie ma średnią równą zero.Aby uzyskać więcej informacji na temat bezpiecznego używania metod w wyrażeniach kwerend, zobacz Porady: obsługa wyjątków w wyrażeniach kwerend (Przewodnik programowania w języku C#).

class GroupSample2
{
    // The element type of the data source. 
    public class Student
    {
        public string First { get; set; }
        public string Last { get; set; }
        public int ID { get; set; }
        public List<int> Scores;
    }

    public static List<Student> GetStudents()
    {
        // Use a collection initializer to create the data source. Note that each element 
        //  in the list contains an inner sequence of scores.
        List<Student> students = new List<Student>
        {
           new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 72, 81, 60}},
           new Student {First="Claire", Last="O'Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}},
           new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int> {99, 89, 91, 95}},
           new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int> {72, 81, 65, 84}},
           new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {97, 89, 85, 82}} 
        };

        return students;

    }

    // This method groups students into percentile ranges based on their 
    // grade average. The Average method returns a double, so to produce a whole 
    // number it is necessary to cast to int before dividing by 10.  
    static void Main()
    {
        // Obtain the data source.
        List<Student> students = GetStudents();

        // Write the query. 
        var studentQuery =
            from student in students
            let avg = (int)student.Scores.Average()
            group student by (avg == 0 ? 0 : avg / 10) into g
            orderby g.Key
            select g;            

        // Execute the query. 
        foreach (var studentGroup in studentQuery)
        {
            int temp = studentGroup.Key * 10;
            Console.WriteLine("Students with an average between {0} and {1}", temp, temp + 10);
            foreach (var student in studentGroup)
            {
                Console.WriteLine("   {0}, {1}:{2}", student.Last, student.First, student.Scores.Average());
            }
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
     Students with an average between 70 and 80
       Omelchenko, Svetlana:77.5
       O'Donnell, Claire:72.25
       Garcia, Cesar:75.5
     Students with an average between 80 and 90
       Garcia, Debra:88.25
     Students with an average between 90 and 100
       Mortensen, Sven:93.5
 */

Grupowanie według kluczy kompozytowe

Za pomocą klucza złożonego chcesz elementy grupy, zgodnie z więcej niż jednego klawisza.Można utworzyć klucz złożony za pomocą typ anonimowy lub typ nazwany do przechowywania kluczowym elementem.W poniższym przykładzie założono, że klasa Person została zadeklarowana z członków o nazwie surname i city.group Klauzuli powoduje, że oddzielne grupy ma być utworzony dla każdego zestawu osoby o to samo nazwisko i tym samym mieocie.

group person by new {name = person.surname, city = person.city};

Jeśli zmienna kwerendy musi przekazać do innej metody, należy użyć typu nazwanego.Utworzyć specjalną klasę przy użyciu właściwości auto wdrożone dla kluczy, a następnie zastąpić Equals i GetHashCode metody.Można również użyć struct, w którym to przypadku ściśle trzeba zastąpić te metody.Aby uzyskać więcej informacji, zobacz Porady: implementowanie klasy lekkiej przy użyciu automatycznie implementowanych właściwości (Przewodnik programowania w języku C#) i Porady: zapytanie o zduplikowane pliki w drzewie katalogu (LINQ).Ten ostatni temat zawiera przykładowy kod, który demonstruje, jak użyć klucza złożonego z nazwanym typem.

Przykład

Poniższy przykład pokazuje wzorzec standardowy do porządkowania danych źródłowych w grupach po logiki nie dodatkowych kwerend jest stosowane do grup.Jest to nazywane grupowania bez kontynuacji.Elementy w tablicy ciągów są grupowane zgodnie z ich pierwszej litery.Wynik kwerendy jest IGrouping typu, który zawiera publicznego Key właściwość typu char i IEnumerable kolekcji, która zawiera każdego elementu w zgrupowania.

Wynik group klauzuli jest sekwencją sekwencji.W związku z tym, aby uzyskać dostęp do poszczególnych elementów w obrębie każdej grupy zwracane, użyj zagnieżdżonych foreach pętli wewnątrz pętli, która wykonuje iteracje klucze grup, jak pokazano w poniższym przykładzie.

class GroupExample1
{
    static void Main()
    {
        // Create a data source. 
        string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese" };

        // Create the query. 
        var wordGroups =
            from w in words
            group w by w[0];

        // Execute the query. 
        foreach (var wordGroup in wordGroups)
        {
            Console.WriteLine("Words that start with the letter '{0}':", wordGroup.Key);
            foreach (var word in wordGroup)
            {
                Console.WriteLine(word);
            }
        }

        // Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }        
}
/* Output:
      Words that start with the letter 'b':
        blueberry
        banana
      Words that start with the letter 'c':
        chimpanzee
        cheese
      Words that start with the letter 'a':
        abacus
        apple
     */

W tym przykładzie pokazuje, jak przeprowadzić dodatkowe logikę w grupach po ich utworzeniu, za pomocą kontynuacji z into.Aby uzyskać więcej informacji, zobacz into (odwołanie w C#).Poniższy przykład kwerendy każdej grupy, zaznacz tylko te, których wartość klucza jest samogłoski.

class GroupClauseExample2
{
    static void Main()
    {
        // Create the data source. 
        string[] words2 = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese", "elephant", "umbrella", "anteater" };

        // Create the query. 
        var wordGroups2 =
            from w in words2
            group w by w[0] into grps
            where (grps.Key == 'a' || grps.Key == 'e' || grps.Key == 'i'
                   || grps.Key == 'o' || grps.Key == 'u')
            select grps;

        // Execute the query. 
        foreach (var wordGroup in wordGroups2)
        {
            Console.WriteLine("Groups that start with a vowel: {0}", wordGroup.Key);
            foreach (var word in wordGroup)
            {
                Console.WriteLine("   {0}", word);
            }
        }

        // Keep the console window open in debug mode
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    Groups that start with a vowel: a
        abacus
        apple
        anteater
    Groups that start with a vowel: e
        elephant
    Groups that start with a vowel: u
        umbrella
*/

Uwagi

W czasie kompilacji group klauzul zostały przetłumaczone na wywołania GroupBy``2 metody.

Zobacz też

Zadania

Porady: tworzenie grup zagnieżdżonych (Przewodnik programowania w języku C#)

Porady: grupowanie wyników kwerendy (Przewodnik programowania w języku C#)

Porady: wykonanie podzapytania w operacji grupowania (Przewodnik programowania w języku C#)

Informacje

IGrouping

GroupBy``2

ThenBy``2

ThenByDescending``2

Koncepcje

Wyrażenia kwerend LINQ (Przewodnik programowania w języku C#)

Inne zasoby

Słowa kluczowe zapytania (odwołanie w C#)