Distinct / DistinctBy în C# (.NET)

LINQ (Language Integrated Query) .NET Framework 3.5 (DistinctBy: .NET 6)

Elimină duplicatele dintr-o secvență; DistinctBy compară după o cheie (de exemplu clientul) și păstrează primul element.

Sintaxă C#
sursa.Distinct()   sursa.Distinct(StringComparer.OrdinalIgnoreCase)   sursa.DistinctBy(x => x.Cheie)

Ce face Distinct / DistinctBy

Distinct() păstrează fiecare valoare o singură dată, folosind egalitatea implicită a tipului. Pentru șiruri poți da un comparator, de exemplu StringComparer.OrdinalIgnoreCase, ca „Iași” și „iași” să fie considerate la fel.

DistinctBy(cheie) (.NET 6) compară elementele după o proprietate și păstrează primul element pentru fiecare cheie, de exemplu prima comandă a fiecărui client. Pentru operații pe mulțimi există și Union, Intersect, Except și variantele lor By.

Pentru clase proprii, Distinct() compară referințele, nu valorile, dacă tipul nu suprascrie Equals/GetHashCode. Un record are egalitate după valori gata făcută.

Exemple

Exemplul 1: Orașe unice, cu și fără majuscule

string[] orase = ["Iași", "Cluj", "iași", "Iași", "Arad", "Cluj"];

Console.WriteLine(string.Join(", ", orase.Distinct()));
Console.WriteLine(string.Join(", ", orase.Distinct(StringComparer.OrdinalIgnoreCase)));
Console.WriteLine(orase.Distinct().Count());

Rezultat

Iași, Cluj, iași, Arad
Iași, Cluj, Arad
4

Exemplul 2: Prima comandă a fiecărui client

Comanda[] comenzi =
[
    new(101, "Ana", 250),
    new(102, "Mihai", 90),
    new(103, "Ana", 40),
    new(104, "Ioana", 120),
    new(105, "Mihai", 300),
];

foreach (var c in comenzi.DistinctBy(c => c.Client))
    Console.WriteLine($"{c.Client}: comanda {c.Id}");

Console.WriteLine(new[] { new Comanda(1, "Ana", 5), new Comanda(1, "Ana", 5) }.Distinct().Count());

record Comanda(int Id, string Client, int Total);

Rezultat

Ana: comanda 101
Mihai: comanda 102
Ioana: comanda 104
1

Greșeli frecvente

  • Distinct() pe obiecte dintr-o clasă obișnuită nu elimină nimic dacă sunt instanțe diferite cu aceleași date. Folosește DistinctBy, un record sau un IEqualityComparer<T>.
  • Documentația nu garantează ordinea rezultatului; dacă ordinea contează, adaugă un OrderBy după Distinct.

Comenzi înrudite