Úkol kolekce objektů - filtrování
| Site: | Moodle ZČU |
| Course: | BP Luboš Dokulil Sada rozšiřujících úloh v Blazor pro předmět Programování 2 |
| Book: | Úkol kolekce objektů - filtrování |
| Printed by: | Nepřihlášený host |
| Date: | Sunday, 18 October 2026, 3:08 AM |
Description
V Zadání úkolu najdete jednoduchý úkol, který objasňuje příkazy jako Where, Select, GroupBy apod.
1. Zadání úkolu
Co je cílem zadání?
- Vytvoření dvou tříd Zaměstnanec a Oddělení pro evidenci osob a statistické výstupy.
- Vytvoření seznamu zaměstnanců a následné strukturované zobrazení dat do připraveného informačního dashboardu.
- Získání a výpočet základních metrik z dat, jako je celkový počet zaměstnanců, celkové mzdové náklady, průměrný a nejvyšší plat.
- Vyfiltrování a seřazení konkrétní podskupiny dat pro zobrazení nadstandardně placených osob a extrakce pouhých jmen do textového výpisu.
- Seskupení dat podle oddělení a jejich přeměna na nové statistické objekty, vyhledání konkrétního záznamu a ověření zadané platové podmínky.
Zadání
Vytvořte třídu Zamestnanec, která bude reprezentovat pracovníka firmy a bude mít vlastnosti Id, Jmeno, Oddeleni a Plat.
Dále vytvořte pomocnou třídu Oddeleni, která bude sloužit pro uložení vypočítaných statistik. Tato třída bude mít vlastnosti NazevOddeleni, PocetZamestnancu a CelkoveNaklady.
V Razor komponentě vytvořte kolekci objektů (seznam), která bude sloužit jako zdroj dat a uchovávat instance třídy Zamestnanec. Tento seznam rovnou naplňte několika testovacími záznamy s různými odděleními a platy.
Aplikaci naprogramujte tak, aby analyzovala data z tohoto seznamu a přehledně je vypsala do stránky. Zaměřte se na využití metod pro filtrování, řazení, seskupování a matematické výpočty nad kolekcí. Výsledek seskupování (GroupBy()) uložte právě do připravených instancí třídy Oddeleni.
Cílem je vytvořit analytický panel (dashboard), který uživateli zobrazí:
- Celkové statistiky podniku (počet lidí, průměrný plat, celkové mzdové náklady).
- Seznam nadstandardně placených zaměstnanců seřazený od nejvyššího platu.
- Souhrnnou tabulku, která rozdělí zaměstnance podle oddělení a sečte pro ně náklady.
- Výsledek vyhledání konkrétního člověka podle jeho ID.
Příklad, jak by mohla stránka vypadat:
Pokud se okno nenačetlo, klikněte zde.
2. Grafická nápověda
Logika u výpisu nadstandartně placených zaměstnanců

Prvním krokem je metoda .Where(), která zafunguje jako síto a propustí k dalšímu zpracování pouze záznamy s platem 60 000 a vyšším. Tento zredukovaný tok dat okamžitě přebírá metoda .OrderByDescending(), která zaměstnance seřadí sestupně od nejvyššího platu.
Vyfiltrovaný a seřazený výsledek je následně vygenerován jako nový zkrácený seznam, který může být přímo vypsán na obrazovku uživateli.
Logika u výpisu nákladů jednotlivých oddělení

Nejprve se data pomocí metody .GroupBy() rozdělí do menších podskupin podle názvu oddělení. Následně metoda .Select() vytvoří pro každou tuto skupinu nový souhrnný záznam, do kterého pomocí metod .Count() a .Sum() rovnou vypočítá požadované statistiky.
3. Řešení úkolu
Třída Zaměstnanec
namespace kolekce_objektu_filtrovani.Models { public class Zamestnanec { public int Id { get; set; } public string Jmeno { get; set; } = ""; public string Oddeleni { get; set; } = ""; public double Plat { get; set; } } }
Třída Zaměstnanec slouží jako datový model. Definuje vlastnosti Id, Jméno, Oddělení a Plat, které musí mít každý evidovaný pracovník. Instance této třídy budeme ukládat do seznamu (kolekce).
Třída Oddělení
namespace kolekce_objektu_filtrovani.Models { public class Oddeleni { public string NazevOddeleni { get; set; } = ""; public int PocetZamestnancu { get; set; } public double CelkoveNaklady { get; set; } } }
Třída Oddělení slouží jako pomocný datový model pro uložení výsledků našeho seskupování (pomocí metody GroupBy a Select). Definuje vlastnosti Název oddělení, Počet zaměstnanců a Celkové náklady, do kterých budeme ukládat vypočítané souhrnné statistiky k následnému vypsání do tabulky.
Razor komponenta
@page "/" @using kolekce_objektu_filtrovani.Models <PageTitle>Home</PageTitle> <h3>Personální Dashboard - Analýza dat</h3> <div class="row text-center mb-4"> <div class="col-md-3"> <div class="card bg-light p-3"> <h6>Počet zaměstnanců</h6> <h4>@CelkovyPocet</h4> </div> </div> <div class="col-md-3"> <div class="card bg-light p-3"> <h6>Mzdové náklady (Měsíc)</h6> <h4>@CelkoveMzdoveNaklady.ToString("C0")</h4> </div> <!-- C0 udává měnu (C = koruny) a počet desetinných míst (v našem případě 0) --> </div> <div class="col-md-3"> <div class="card bg-light p-3"> <h6>Průměrný plat</h6> <h4>@PrumernyPlat.ToString("C0")</h4> </div> </div> <div class="col-md-3"> <div class="card bg-light p-3"> <h6>Nejvyšší plat</h6> <h4>@NejvyssiPlat.ToString("C0")</h4> </div> </div> </div> <div class="row"> <div class="col-md-6 mb-3"> <div class="card p-3 h-100"> <h5>Nadstandardně placení (Nad 60k)</h5> <p>Seřazeno od nejlépe placeného (Where + OrderBy)</p> <ul> @foreach (var z in DobrePlaceni) { <li>@z.Jmeno - @z.Plat.ToString("C0")</li> } </ul> <hr /> <h5>Pouze jména zaměstnanců (Select)</h5> <p>@string.Join(", ", SeznamJmen)</p> </div> <!-- Join(", "); vypíše všechny položky v kolekci a oddělí je čárkou --> </div> <div class="col-md-6 mb-3"> <div class="card p-3 h-100"> <h5>Náklady podle oddělení (GroupBy + Select)</h5> <table class="table table-sm mt-3"> <thead> <tr> <th>Oddělení</th> <th>Počet lidí</th> <th>Celkové platy</th> </tr> </thead> <tbody> @foreach (var stat in StatistikyPodleOddeleni) { <tr> <td><strong>@stat.NazevOddeleni</strong></td> <td>@stat.PocetZamestnancu</td> <td>@stat.CelkoveNaklady.ToString("C0")</td> </tr> } </tbody> </table> <hr /> <h5>Hledání (FirstOrDefault & Any)</h5> <p> <strong>Zaměstnanec s ID 3:</strong> @(HledanyZamestnanec != null ? HledanyZamestnanec.Jmeno : "Nenalezen") </p> <p> <strong>Máme zaměstnance s platem nad 100k?</strong> @(VysokyPlat ? "Ano" : "Ne") </p> </div> </div> </div> @code { private List<Zamestnanec> zamestnanci = new List<Zamestnanec> // Zdrojová kolekce zaměstnanců { new Zamestnanec { Id = 1, Jmeno = "Jan Novák", Oddeleni = "IT", Plat = 75000 }, new Zamestnanec { Id = 2, Jmeno = "Eva Malá", Oddeleni = "HR", Plat = 45000 }, new Zamestnanec { Id = 3, Jmeno = "Petr Svoboda", Oddeleni = "IT", Plat = 82000 }, new Zamestnanec { Id = 4, Jmeno = "František Dvořák", Oddeleni = "Marketing", Plat = 55000 }, new Zamestnanec { Id = 5, Jmeno = "Karel Šmíd", Oddeleni = "Management", Plat = 120000 } }; private int CelkovyPocet => zamestnanci.Count(); // .Count() spočítá všechny prvky v seznamu private double CelkoveMzdoveNaklady => zamestnanci.Sum(z => z.Plat); // .Sum() projde zaměstnance a sečte jejich platy private double PrumernyPlat => zamestnanci.Average(z => z.Plat); // .Average() vypočítá aritmetický průměr platů private double NejvyssiPlat => zamestnanci.Max(z => z.Plat); // .Max() najde absolutně nejvyšší hodnotu platu private bool VysokyPlat => zamestnanci.Any(z => z.Plat > 100000); // .Any() vrací true, pokud alespoň jeden splní podmínku private Zamestnanec HledanyZamestnanec => zamestnanci.FirstOrDefault(z => z.Id == 3); // .FirstOrDefault() najde prvního s ID 3, jinak vrátí null private List<Zamestnanec> DobrePlaceni => zamestnanci.Where(z => z.Plat >= 60000).OrderByDescending(z => z.Plat).ToList(); // .Where() vyfiltruje data a .OrderByDescending() je seřadí sestupně private List<string> SeznamJmen => zamestnanci.Select(z => z.Jmeno).ToList(); // .Select() extrahuje z objektů pouze vlastnost Jméno (vytvoří seznam textů) private List<Oddeleni> StatistikyPodleOddeleni => zamestnanci .GroupBy(z => z.Oddeleni) // Rozdělí lidi do skupin (IT, HR, Management...) .Select(skupina => new Oddeleni // Z každé skupiny vytvoří jeden statistický objekt { NazevOddeleni = skupina.Key, // .Key obsahuje to, podle čeho se seskupovalo (název) PocetZamestnancu = skupina.Count(), // Spočítá lidi uvnitř dané skupiny CelkoveNaklady = skupina.Sum(z => z.Plat) // Sečte platy pouze lidem v dané skupině }) .ToList(); // Výsledek převede na klasický List }
V části @code se nachází zdrojová kolekce zamestnanci naplněná daty. Agregační metody (např. .Count(), .Sum(), .Average()) provádějí matematické výpočty z celé sady dat a vracejí jedinou hodnotu.
Pro zápis podmínek uvnitř metod používáme tzv. lambda výrazy (např. z => z.Plat). Písmeno z si volíme sami a funguje jako zástupný název pro jednoho konkrétního zaměstnance, kterého příkaz zrovna kontroluje. Šipka => pak programu přesně říká, s jakou vlastností tohoto zaměstnance chceme pracovat.
.Where(z => z.Plat >= 60000) nejprve vybere pouze zaměstnance splňující zadanou podmínku (plat nad 60 000). Na tento zredukovaný výsledek se aplikuje .OrderByDescending(), která data seřadí sestupně. A nakonec metoda .ToList() uloží do klasického seznamu.
.Select(z => z.Jmeno) projde všechny záznamy a vytáhne z nich jen to, co jsme šipkou určili ("z každého zaměstnance z vyber jen jeho jméno"). Místo složitých objektů tak získáme jednoduchý seznam textů (List<string>).
.GroupBy(z => z.Oddeleni) rozdělí lidi do menších skupin podle oddělení. Navazující .Select(skupina => new Oddeleni {...}) pak už nepracuje s jednotlivci, ale vezme rovnou celou vzniklou skupinu a vytvoří z ní jeden nový souhrnný objekt. Přitom se pomocí .Count() a .Sum() rovnou vypočítají statistiky, které se izolovaně aplikují pouze na lidi uvnitř právě zpracovávané skupiny.