group — Klauzula (odwołanie w C#)group clause (C# Reference)

group Klauzula zwraca sekwencję IGrouping<TKey,TElement> obiektów zawierających zero lub więcej elementów, które odpowiadają wartości klucza dla grupy.The group clause returns a sequence of IGrouping<TKey,TElement> objects that contain zero or more items that match the key value for the group. Na przykład można pogrupować sekwencją ciągów, zgodnie z pierwszą literę każdego ciągu.For example, you can group a sequence of strings according to the first letter in each string. W takim przypadku pierwsza litera jest kluczem i ma typ chari jest przechowywany w Key właściwości każdego IGrouping<TKey,TElement> obiektu.In this case, the first letter is the key and has a type char, and is stored in the Key property of each IGrouping<TKey,TElement> object. Kompilator wnioskuje typ klucza.The compiler infers the type of the key.

Możesz zakończyć wyrażeniu zapytania z group klauzuli, jak pokazano w poniższym przykładzie:You can end a query expression with a group clause, as shown in the following example:

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

Jeśli chcesz wykonać operacje zapytań dodatkowe w każdej grupie, należy określić identyfikator tymczasowy, za pomocą do kontekstowego słowa kluczowego.If you want to perform additional query operations on each group, you can specify a temporary identifier by using the into contextual keyword. Kiedy używasz into, należy kontynuować z zapytaniem, a po pewnym czasie Zakończ ją albo select instrukcji lub innego group klauzuli, jak pokazano w poniższym fragmencie:When you use into, you must continue with the query, and eventually end it with either a select statement or another group clause, as shown in the following excerpt:

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

Bardziej kompletne przykłady stosowania group z lub bez into znajdują się w sekcji przykład tego artykułu.More complete examples of the use of group with and without into are provided in the Example section of this article.

Wyliczanie wyników zapytania grupyEnumerating the results of a group query

Ponieważ IGrouping<TKey,TElement> obiekty utworzone przez group zapytania są zasadniczo listę list, korzystając z zagnieżdżonej foreach pętli, aby mieć dostęp do elementów w każdej grupie.Because the IGrouping<TKey,TElement> objects produced by a group query are essentially a list of lists, you must use a nested foreach loop to access the items in each group. Zewnętrzna pętla wykonuje iterację na klucze grupy, a wewnętrzną pętlę iteruje przez każdy element w samej grupy.The outer loop iterates over the group keys, and the inner loop iterates over each item in the group itself. Grupa może mieć klucza, ale żadne elementy.A group may have a key but no elements. Poniżej przedstawiono foreach pętli, która wykonuje zapytanie w poprzednich przykładach kodu:The following is the foreach loop that executes the query in the previous code examples:

// 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 kluczyKey types

Klucze grupy mogą być dowolnego typu, takie jak ciąg, wbudowanego typu liczbowego lub zdefiniowanej przez użytkownika o nazwie typu lub typu anonimowego.Group keys can be any type, such as a string, a built-in numeric type, or a user-defined named type or anonymous type.

Grupowanie według ciąguGrouping by string

W poprzednich przykładach kodu używany char.The previous code examples used a char. Klucza typu ciąg można łatwo określono zamiast tego, na przykład Pełna nazwa ostatnich:A string key could easily have been specified instead, for example the complete last name:

// 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 boolGrouping by bool

Poniższy przykład pokazuje użycie wartość bool klawisz aby podzielić wyniki na dwie grupy.The following example shows the use of a bool value for a key to divide the results into two groups. Należy pamiętać, że wartość jest generowany przez Podwyrażenie w group klauzuli.Note that the value is produced by a sub-expression in the group clause.

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 liczbowegoGrouping by numeric range

W następnym przykładzie użyto wyrażenia, aby utworzyć klucze grupy numeryczne, które reprezentują zakres percentyl.The next example uses an expression to create numeric group keys that represent a percentile range. Zwróć uwagę na użycie umożliwiają jako wygodną lokalizację do przechowywania metodę wywołania wynik, dzięki czemu nie trzeba wywoływać metodę dwa razy w group klauzuli.Note the use of let as a convenient location to store a method call result, so that you don't have to call the method two times in the group clause. Aby uzyskać więcej informacji o tym, jak bezpiecznie używać metod w wyrażeniach zapytań, zobacz jak: Obsługa wyjątków w wyrażeniach zapytań.For more information about how to safely use methods in query expressions, see How to: Handle Exceptions in Query Expressions.

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 / 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 złożonychGrouping by composite keys

Umożliwia grupowanie elementów według więcej niż jeden klucz za pomocą klucza złożonego.Use a composite key when you want to group elements according to more than one key. Klucz złożony możesz utworzyć przy użyciu typu anonimowego lub typem nazwanym do przechowywania klucza elementu.You create a composite key by using an anonymous type or a named type to hold the key element. W poniższym przykładzie przyjęto założenie, że klasa Person został zadeklarowany za pomocą elementów członkowskich o nazwie surname i city.In the following example, assume that a class Person has been declared with members named surname and city. group Klauzuli powoduje, że ma zostać utworzony dla każdego zestawu osób z tej samej nazwisko i tym samym mieście osobnej grupy.The group clause causes a separate group to be created for each set of persons with the same last name and the same city.

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

Jeśli zmienna zapytania musi pomyślnie przejść do innej metody, należy użyć typu nazwanego.Use a named type if you must pass the query variable to another method. Utwórz klasę specjalnych kluczy przy użyciu automatycznie implementowanych właściwości, a następnie zastąpić Equals i GetHashCode metody.Create a special class using auto-implemented properties for the keys, and then override the Equals and GetHashCode methods. Można również użyć struktury, w którym to przypadku ściśle trzeba zastąpić te metody.You can also use a struct, in which case you do not strictly have to override those methods. Aby uzyskać więcej informacji, zobacz jak: Implementowanie klasy Lightweight przy użyciu automatycznie implementowanych właściwości i jak: Zapytanie o zduplikowane pliki w drzewie katalogu.For more information see How to: Implement a Lightweight Class with Auto-Implemented Properties and How to: Query for Duplicate Files in a Directory Tree. Ostatni artykuł zawiera przykładowy kod, który demonstruje sposób skorzystania z kluczem złożonym z typem nazwanym.The latter article has a code example that demonstrates how to use a composite key with a named type.

PrzykładExample

Poniższy przykład pokazuje standardowego wzorca porządkowania danych źródłowych w grupach, stosowania logiki nie dodatkowych zapytania do grup.The following example shows the standard pattern for ordering source data into groups when no additional query logic is applied to the groups. Jest to grupa bez kontynuacji.This is called a grouping without a continuation. Elementy w tablicy ciągów są pogrupowane według ich pierwszą literę.The elements in an array of strings are grouped according to their first letter. Wynik zapytania jest IGrouping<TKey,TElement> typu, który zawiera publiczny Key właściwości typu char i IEnumerable<T> kolekcji, która zawiera każdy element na grupowanie.The result of the query is an IGrouping<TKey,TElement> type that contains a public Key property of type char and an IEnumerable<T> collection that contains each item in the grouping.

Wynik group klauzula jest sekwencji.The result of a group clause is a sequence of sequences. W związku z tym, aby uzyskać dostęp do poszczególnych elementów w każdej grupie zwrócone, użyj zagnieżdżoną foreach pętli wewnątrz pętli, który iteruje po klucze grupy, jak pokazano w poniższym przykładzie.Therefore, to access the individual elements within each returned group, use a nested foreach loop inside the loop that iterates the group keys, as shown in the following example.

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
     */

PrzykładExample

W tym przykładzie przedstawiono sposób wykonywania dodatkowej logiki w grupach, po ich utworzeniu, za pomocą kontynuacji z into.This example shows how to perform additional logic on the groups after you have created them, by using a continuation with into. Aby uzyskać więcej informacji, zobacz do.For more information, see into. Poniższy przykład wysyła zapytanie do każdej grupy, aby wybrać tylko te, których wartość klucza jest samogłosek.The following example queries each group to select only those whose key value is a vowel.

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
*/    

UwagiRemarks

W czasie kompilacji group klauzule są tłumaczone na wywołania GroupBy metody.At compile time, group clauses are translated into calls to the GroupBy method.

Zobacz takżeSee also