gruppsats (C#-referens)
- group
satsen returnerar en sekvens med IGrouping<TKey,TElement> objekt som innehåller noll eller fler objekt som matchar nyckelvärdet för gruppen. Du kan till exempel gruppera en sekvens med strängar enligt den första bokstaven i varje sträng. I det här fallet är den första bokstaven nyckeln och har en typtecken och lagras i Key
egenskapen för varje IGrouping<TKey,TElement> objekt. Kompilatorn härleder typen av nyckel.
Du kan avsluta ett frågeuttryck med en group
sats, som du ser i följande exempel:
// Query variable is an IEnumerable<IGrouping<char, Student>>
var studentQuery1 =
from student in students
group student by student.Last[0];
Om du vill utföra ytterligare frågeåtgärder för varje grupp kan du ange en tillfällig identifierare med hjälp av det kontextuella nyckelordet. När du använder into
måste du fortsätta med frågan och slutligen avsluta den med antingen en instruktion eller en select
annan group
sats, som du ser i följande utdrag:
// 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;
Mer fullständiga exempel på användning av group
med och utan into
finns i avsnittet Exempel i den här artikeln.
Räkna upp resultatet av en gruppfråga
Eftersom objekten IGrouping<TKey,TElement> som skapas av en group
fråga i princip är en lista med listor måste du använda en kapslad foreach-loop för att komma åt objekten i varje grupp. Den yttre loopen itererar över gruppnycklarna och den inre loopen itererar över varje objekt i själva gruppen. En grupp kan ha en nyckel men inga element. Följande är den foreach
loop som kör frågan i föregående kodexempel:
// 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);
}
}
Nyckeltyper
Gruppnycklar kan vara valfri typ, till exempel en sträng, en inbyggd numerisk typ eller en användardefinierad namngiven typ eller anonym typ.
Gruppera efter sträng
I föregående kodexempel användes en char
. En strängnyckel kunde enkelt ha angetts i stället, till exempel det fullständiga efternamn:
// 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;
Gruppering efter bool
I följande exempel visas användningen av ett bool-värde för en nyckel för att dela upp resultatet i två grupper. Observera att värdet skapas av ett underuttryck i group
-satsen.
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
*/
Gruppera efter numeriskt intervall
I nästa exempel används ett uttryck för att skapa numeriska gruppnycklar som representerar ett percentilintervall. Observera användningen av let som en lämplig plats för att lagra ett metodanropsresultat, så att du inte behöver anropa metoden två gånger i group
-satsen. Mer information om hur du använder metoder i frågeuttryck på ett säkert sätt finns i Hantera undantag i frågeuttryck.
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
*/
Gruppera efter sammansatta nycklar
Använd en sammansatt nyckel när du vill gruppera element enligt mer än en nyckel. Du skapar en sammansatt nyckel med hjälp av en anonym typ eller en namngiven typ för att lagra nyckelelementet. I följande exempel antar du att en klass Person
har deklarerats med medlemmar med namnet surname
och city
. Satsen group
gör att en separat grupp skapas för varje uppsättning personer med samma efternamn och samma stad.
group person by new {name = person.surname, city = person.city};
Använd en namngiven typ om du måste skicka frågevariabeln till en annan metod. Skapa en särskild klass med hjälp av automatiskt implementerade egenskaper för nycklarna och åsidosätt Equals sedan metoderna och GetHashCode . Du kan också använda en struct, i vilket fall du inte strikt behöver åsidosätta dessa metoder. Mer information finns i Så här implementerar du en lättviktsklass med automatiskt implementerade egenskaper och Så här frågar du efter dubblettfiler i ett katalogträd. Den senare artikeln har ett kodexempel som visar hur du använder en sammansatt nyckel med en namngiven typ.
Exempel 1
I följande exempel visas standardmönstret för att sortera källdata i grupper när ingen ytterligare frågelogik tillämpas på grupperna. Detta kallas för en gruppering utan fortsättning. Elementen i en matris med strängar grupperas enligt deras första bokstav. Resultatet av frågan är en IGrouping<TKey,TElement> typ som innehåller en offentlig Key
egenskap av typen char
och en IEnumerable<T> samling som innehåller varje objekt i gruppering.
Resultatet av en group
sats är en sekvens med sekvenser. För att komma åt de enskilda elementen i varje returnerad grupp använder du därför en kapslad foreach
loop i loopen som itererar gruppnycklarna, som du ser i följande exempel.
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
*/
Exempel 2
Det här exemplet visar hur du utför ytterligare logik i grupperna när du har skapat dem med hjälp av en fortsättning med into
. Mer information finns i. I följande exempel uppmanas varje grupp att endast välja de vars nyckelvärde är en vokal.
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
*/
Kommentarer
Vid kompileringstillfället group
översätts satser till anrop till GroupBy metoden.
Anpassad likhetsjämförare stöds inte i syntaxen för satsfrågan group
. Använd GroupBy metoden explicit om du vill använda IEqualityComparer i din fråga.