Sdílet prostřednictvím


Postupy: Seskupení výsledků dotazu (Průvodce programováním v C#)

Seskupení je jedním z nejdůležitějších funkcí LINQ.Následující příklady ukazují, jak seskupit data různými způsoby:

  • Jedinou vlastností.

  • První písmeno vlastnost řetězce.

  • Pomocí vypočítaného číselném rozsahu.

  • Logická predikát nebo jiný výraz.

  • Složený klíč.

Kromě toho poslední dva dotazy projektu jejich výsledků do nové anonymní typ, který obsahuje pouze student's první a poslední jméno.Další informace naleznete group – klauzule (Referenční dokumentace jazyka C#).

Příklad

Všechny příklady v tomto tématu použít následující pomocné třídy a data zdrojů.

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

Následující příklad ukazuje, jak seskupit prvky zdroj pomocí jedné vlastnosti prvku jako skupinový klíč.V tomto případě je klíč string, příjmení studenta.Je také možné použít řetězec pro klíč.Seskupení operace používá výchozí porovnávací nástroj rovnosti typu.

Vložte následující metodu do StudentClass třídy.Změna volajícího prohlášení v Main metody 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
*/

Následující příklad ukazuje, jak seskupit prvky zdroj něco jiného než vlastnost objektu pomocí klíče skupiny.Klíč v tomto příkladu je první písmeno příjmení studenta.

Vložte následující metodu do StudentClass třídy.Změna volajícího prohlášení v Main metody 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
*/

Následující příklad ukazuje, jak seskupit prvky zdroj pomocí číselný rozsah jako klíč skupiny.Výsledky dotazu pak projekty do anonymní typ, který obsahuje pouze jméno a příjmení a percentily oblast, do které patří student.Anonymní typ se používá, protože není nutné použít úplnou Student objektu zobrazení výsledků.GetPercentilezaložen na průměrné skóre Studentova pomocné funkce pro výpočet percentil je možné.Metoda vrátí celé číslo mezi 0 a 10.

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

Vložte následující metodu do StudentClass třídy.Změna volajícího prohlášení v Main metody 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
*/

Následující příklad ukazuje, jak seskupit prvky zdroj pomocí logické porovnání výrazů.V tomto příkladu logický výraz testuje, zda je větší než 75 Studentovým zkoušku průměrné skóre.Jako v předchozích příkladech jsou výsledky promítnutí do anonymní typ, protože úplný zdrojový prvek není zapotřebí.Všimněte si, že se vlastnosti v anonymní typ vlastnosti na Key člena a lze podle názvu při spuštění dotazu.

Vložte následující metodu do StudentClass třídy.Změna volajícího prohlášení v Main metody 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
*/

Následující příklad ukazuje, jak pomocí anonymní typ zapouzdření klíč, který obsahuje více hodnot.V tomto příkladu je první hodnota klíče první písmeno příjmení studenta.Druhá hodnota klíče je logická hodnota, která určuje, zda student znamená více než 85 první zkoušku.Skupiny můžete objednat všechny vlastnosti v klíči.

Vložte následující metodu do StudentClass třídy.Změna volajícího prohlášení v Main metody 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
*/

Probíhá kompilace kódu

Kopírování a vkládání každou metodu, kterou chcete testovat do StudentClass třídy.Přidat volání příkazu pro metodu, která Main metoda a stiskněte klávesu F5.

Při těchto metod se přizpůsobit vlastní aplikace, nezapomeňte, že vyžaduje LINQ verze 3.5 nebo 4 .NET Framework, a že projekt musí obsahovat odkaz na System.Core.dll a použitím směrnice pro System.Linq.LINQ SQL, XML LINQ a LINQ DataSet typy vyžadují další používání směrnic a odkazy.Další informace naleznete v tématu Postupy: Vytvoření projektu LINQ.

Viz také

Úkoly

Postupy: Provádění poddotazů na skupinách (Průvodce programováním v C#)

Postupy: Vytvoření vnořené skupiny (Průvodce programováním v C#)

Referenční dokumentace

group – klauzule (Referenční dokumentace jazyka C#)

Anonymní typy (Průvodce programováním v C#)

GroupBy``2

IGrouping

Koncepty

LINQ – výrazy dotazů (Průvodce programováním v C#)

Seskupování dat