Neu in .NET 9.0 [22]: LINQ-Operator CountBy()

Ein neuer Operator für Language Integrated Query vereinfacht das Gruppieren nach Häufigkeit.

vorlesen Druckansicht

(Bild: Pincasso/Shutterstock.com)

Lesezeit: 1 Min.
Von
  • Dr. Holger Schwichtenberg

In .NET 9.0 hat Microsoft in der Basisklassenbibliothek den neuen Operator CountBy() für Language Integrated Query (LINQ) hinzugefügt. Wenn nach Häufigkeit gruppiert werden soll, ist es damit nicht mehr nötig, den Operator GroupBy() einzusetzen.

Der Dotnet-Doktor – Holger Schwichtenberg
Der Dotnet-Doktor – Holger Schwichtenberg

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.

Videos by heise

Folgendes Codebeispiel ermittelt die häufigsten Vornamen mit CountBy():

private static List<Person> GetData()
{
 #region ---------------- Demodaten erstellen
 int count = 10000;
 CUI.H3($"Generiere {count} Demodaten...");
 Randomizer.Seed = new Random(42); // Fester Seed fĂĽr gleichbleibende Testdaten!
 var personFaker = new AutoFaker<Person>("de") // Fake-Daten mit https://github.com/nickdodd79/AutoBogus
    .RuleFor(fake => fake.ID, fake => fake.Random.Int(0))
    .RuleFor(fake => fake.Givenname, fake => fake.Name.FirstName())
    .RuleFor(fake => fake.Surname, fake => fake.Name.LastName())
    .RuleFor(fake => fake.Birthday, fake => fake.Date.Past(100).Date)
    .RuleFor(fake => fake.Team, fake => fake.Random.ArrayElement(new string[] { "MSV", "RWE", "BVB" }))
    .RuleFor(fake => fake.Punkte, fake => fake.Random.Number(0, 10));
 List<Person> personSet = new();
 for (int i = 0; i < count; i++)
 {
  var p = personFaker.Generate();
  personSet.Add(p);
 }
 Console.WriteLine("Anzahl Personen: " + personSet.Count);
 #endregion
 return personSet;
}
 
/// <summary>
/// Ermitteln der 10 häufigsten Vornamen in einer Liste von Personen
/// </summary>
public void LINQ_CountBy()
{
 CUI.Demo(nameof(LINQ_CountBy) + ": Ermitteln der 10 häufigsten Vornamen in einer Liste von Personen");
 List<Person> personSet = GetData();
 
 // --------------------------- ALT
 CUI.H2("10 häufigste Vornamen im Datenbestand (alt mit GroupBy() + Select())");
 // bisherige Implementierung mit GroupBy() + Select()
 var nameGroupsOld = personSet
     .GroupBy(info => info.Givenname) // Gruppieren nach Häufigkeit des GivenName
     .Select(group => new
     {
      Key = group.Key,
      Value = group.Count() // Zählen
     });
 
 var groups1top10 = nameGroupsOld.OrderByDescending(x => x.Value).Take(10);
 // Ausgabe mit SpectreConsole
 AnsiConsole.Write(new BarChart()
   .Width(60)
   .AddItems(groups1top10, (item) => new BarChartItem(
       item.Key, item.Value, Color.Cyan1)));
 
 // --------------------------- NEU
 CUI.H2("\n10 häufigste Vornamen im Datenbestand (neu mit CountBy())");
 Dictionary<string, int> nameGroupsNew = personSet
     .CountBy(x => x.Givenname); // Gruppieren nach Häufigkeit des GivenName
 
 Console.WriteLine("10 häufigste Vornamen im Datenbestand:");
 var groups2top10 = nameGroupsNew.OrderByDescending(x => x.Value).Take(10);
 
 // Ausgabe mit SpectreConsole
 AnsiConsole.Write(new BarChart()
   .Width(60)
   .AddItems(groups2top10, (item) => new BarChartItem(
       item.Key, item.Value, Color.Cyan2)));
}

Das Ergebnis von CountBy() ist Dictionary<T, T>, während die bisherige Umsetzung mit GroupBy() einen anonymen Typ liefert.

Die Ausgabe des Beispielcodes nutzt die Zusatzbibliothek SpectreConsole fĂĽr die Balkenausgabe.

(Bild: Screenshot (Holger Schwichtenberg))

(rme)