group tümcesi (C# Başvurusu)

yan tümcesi group IGrouping<TKey,TElement> , grubun anahtar değeriyle eşleşen sıfır veya daha fazla öğe içeren bir nesne dizisi döndürür. Örneğin, bir dizi dizeyi her dizedeki ilk harfe göre gruplandırabilirsiniz. Bu durumda, ilk harf anahtardır ve bir tür karakterine sahiptir ve her IGrouping<TKey,TElement> nesnenin Key özelliğinde depolanır. Derleyici, anahtarın türünü çıkarsar.

Aşağıdaki örnekte gösterildiği gibi sorgu ifadesini yan group tümcesiyle sonlandırabilirsiniz:

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

Her grupta ek sorgu işlemleri gerçekleştirmek istiyorsanız, bağlamsal anahtar sözcüğünü kullanarak geçici bir tanımlayıcı belirtebilirsiniz. kullanırken intosorguya devam etmeniz ve sonunda aşağıdaki alıntıda gösterildiği gibi bir deyim veya başka bir select group yan tümceyle sonlandırmanız gerekir:

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

ile ve olmadan into kullanımına group ilişkin daha eksiksiz örnekler bu makalenin Örnek bölümünde verilmiştir.

Grup sorgusunun sonuçlarını numaralandırma

IGrouping<TKey,TElement> Sorgu tarafından group üretilen nesneler temelde bir liste listesi olduğundan, her gruptaki öğelere erişmek için iç içe foreach döngüsü kullanmanız gerekir. Dış döngü grup anahtarları üzerinde yinelenir ve iç döngü grubun kendisindeki her öğe üzerinde yinelenir. Bir grubun anahtarı olabilir ancak öğe olmayabilir. Önceki kod örneklerinde sorguyu yürüten döngü aşağıda foreach verilmiştir:

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

Anahtar türleri

Grup anahtarları dize, yerleşik sayısal tür veya kullanıcı tanımlı adlandırılmış tür veya anonim tür gibi herhangi bir tür olabilir.

Dizeye göre gruplandırma

Önceki kod örneklerde kullanılmıştır char. Bunun yerine bir dize anahtarı kolayca belirtilebilir, örneğin tam soyadı:

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

Bool'a göre gruplandırma

Aşağıdaki örnekte, sonuçları iki gruba bölmek için bir anahtar için bool değeri kullanımı gösterilmektedir. Değerin yan tümcesindeki group bir alt ifade tarafından üretildiğini unutmayın.

class GroupSample1
{
    // The element type of the data source.
    public class Student
    {
        public required string First { get; init; }
        public required string Last { get; init; }
        public required int ID { get; init; }
        public required 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 Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= [97, 72, 81, 60]},
           new Student {First="Claire", Last="O'Donnell", ID=112, Scores= [75, 84, 91, 39]},
           new Student {First="Sven", Last="Mortensen", ID=113, Scores= [99, 89, 91, 95]},
           new Student {First="Cesar", Last="Garcia", ID=114, Scores= [72, 81, 65, 84]},
           new Student {First="Debra", Last="Garcia", ID=115, Scores= [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());
            }
        }
    }
}
/* 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
*/

Sayısal aralığa göre gruplandırma

Sonraki örnekte, yüzdebirlik aralığı temsil eden sayısal grup anahtarları oluşturmak için bir ifade kullanılır. Yöntemi yan tümcesinde iki kez çağırmak zorunda kalmamak için yöntem çağrısı sonucunu depolamak için uygun bir konum olarak let kullanımına group dikkat edin. Sorgu ifadelerinde yöntemleri güvenli bir şekilde kullanma hakkında daha fazla bilgi için bkz . Sorgu ifadelerindeki özel durumları işleme.

class GroupSample2
{
    // The element type of the data source.
    public class Student
    {
        public required string First { get; init; }
        public required string Last { get; init; }
        public required int ID { get; init; }
        public required 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 Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= [97, 72, 81, 60]},
           new Student {First="Claire", Last="O'Donnell", ID=112, Scores= [75, 84, 91, 39]},
           new Student {First="Sven", Last="Mortensen", ID=113, Scores= [99, 89, 91, 95]},
           new Student {First="Cesar", Last="Garcia", ID=114, Scores= [72, 81, 65, 84]},
           new Student {First="Debra", Last="Garcia", ID=115, Scores= [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());
            }
        }
    }
}
/* 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
 */

Bileşik anahtarlara göre gruplandırma

Öğeleri birden fazla anahtara göre gruplandırmak istediğinizde bileşik anahtar kullanın. Anahtar öğesini tutmak için anonim bir tür veya adlandırılmış bir tür kullanarak bileşik anahtar oluşturursunuz. Aşağıdaki örnekte, ve cityadlı surname üyeler ile bir sınıfın Person bildirildiğini varsayalım. yan tümcesi group , aynı soyadına ve aynı şehre sahip her kişi kümesi için ayrı bir grup oluşturulmasına neden olur.

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

Sorgu değişkenini başka bir yönteme geçirmeniz gerekiyorsa adlandırılmış bir tür kullanın. Anahtarlar için otomatik olarak uygulanan özellikleri kullanarak özel bir sınıf oluşturun ve ardından ve GetHashCode yöntemlerini geçersiz kılınEquals. Ayrıca bir yapı da kullanabilirsiniz. Bu durumda bu yöntemleri kesinlikle geçersiz kılmanız gerekmez. Daha fazla bilgi için bkz . Otomatik olarak uygulanan özelliklere sahip basit bir sınıf uygulama ve Dizin ağacında yinelenen dosyaları sorgulama. İkinci makalede, adlandırılmış bir türle bileşik anahtarın nasıl kullanılacağını gösteren bir kod örneği vardır.

Örnek 1

Aşağıdaki örnek, gruplara ek sorgu mantığı uygulanmadığında kaynak verileri gruplara sıralamak için standart deseni gösterir. Bu, devamlılığı olmayan bir gruplandırma olarak adlandırılır. Dize dizisindeki öğeler ilk harflerine göre gruplandırılır. Sorgunun sonucu, tür ortak özelliğini ve gruplandırmadaki her öğeyi içeren bir koleksiyonu içeren bir IEnumerable<T> türdür IGrouping<TKey,TElement> char.Key

Yan group tümcesinin sonucu bir dizi dizisidir. Bu nedenle, döndürülen her grup içindeki tek tek öğelere erişmek için, aşağıdaki örnekte gösterildiği gibi grup anahtarlarını yineleyen döngü içinde iç içe foreach bir döngü kullanın.

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

Örnek 2

Bu örnek, ile intobir devamlılık kullanarak, oluşturduktan sonra gruplar üzerinde nasıl ek mantık gerçekleştirebileceğinizi gösterir. Daha fazla bilgi için bkz . içine. Aşağıdaki örnek, yalnızca anahtar değeri sesli harf olan kişileri seçmek için her grubu sorgular.

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

Açıklamalar

Derleme zamanında, group yan tümceler yöntemine çağrılara çevrilir GroupBy .

Özel eşitlik karşılaştırıcısı yan tümce sorgusunun group söz diziminde desteklenmez. Sorgunuzda kullanmak IEqualityComparer istiyorsanız yöntemi açıkça kullanınGroupBy.

Ayrıca bkz.