Sortowanie nazw — Zadanie rekrutacyjne #8

Czego szuka rekruter:
StringComparer, porównanie kulturowe,Array.Sortvs LINQ, stabilność sortowania
Poziom: Junior
Zadanie
Posortuj tablicę nazw (stringów) alfabetycznie — rosnąco i malejąco.
Czego szuka rekruter
Sortowanie stringów to pozornie proste zadanie z ukrytymi pułapkami. Rekruter sprawdza:
- Czy kandydat wie, że domyślne porównanie stringów jest
Ordinal— “Z” < “a” (wielkie litery mają niższy kod ASCII) - Czy zna
StringCompareri różnicę międzyOrdinal,OrdinalIgnoreCase,CurrentCulture - Czy rozumie, że
Array.Sortmodyfikuje oryginalną tablicę, a LINQOrderBytworzy nową nullw tablicy —StringComparerobsługuje to inaczej niż porównanie operatorem
Pułapka — sortowanie wielkość-liter-świadome
var names = new[] { "anna", "Zofia", "marek", "Beata" };
Array.Sort(names); // Ordinal domyślnie
// Wynik: "Beata", "Zofia", "anna", "marek"
// Bo 'B' (66) < 'Z' (90) < 'a' (97) < 'm' (109)
// Wielkie litery wchodzą przed małymi!
✅ Poprawne sortowanie — kulturowo-świadome, ignorując wielkość
static string[] SortNames(string[] names, bool ascending = true)
{
if (names == null) throw new ArgumentNullException(nameof(names));
var comparer = StringComparer.CurrentCultureIgnoreCase;
return ascending
? names.OrderBy(n => n, comparer).ToArray()
: names.OrderByDescending(n => n, comparer).ToArray();
}
var names = new[] { "anna", "Zofia", "marek", "Beata", null };
var sorted = SortNames(names);
// Wynik: null, "anna", "Beata", "marek", "Zofia"
Kiedy który StringComparer?
// Ordinal — szybkie, bajt po bajcie, case-sensitive
// Używaj dla: kluczy słownika, identyfikatorów, porównań binarne-równe
StringComparer.Ordinal
// OrdinalIgnoreCase — szybkie, bajt po bajcie, case-insensitive
// Używaj dla: nazw plików, HTTP headerów, kluczy config
StringComparer.OrdinalIgnoreCase
// CurrentCulture — kulturowo-świadome (ą, ę, ó...), case-sensitive
// Używaj dla: danych wyświetlanych użytkownikowi w jego języku
StringComparer.CurrentCulture
// CurrentCultureIgnoreCase — kulturowo-świadome, case-insensitive
// Używaj dla: sortowania nazw dla użytkownika
StringComparer.CurrentCultureIgnoreCase
// InvariantCulture — kultura neutralna, deterministyczna między środowiskami
// Używaj dla: danych do zapisu/odczytu z pliku, API
StringComparer.InvariantCulture
Modyfikacja in-place vs nowa tablica
var names = new[] { "marek", "anna", "zofia" };
// Array.Sort — modyfikuje oryginalną tablicę
Array.Sort(names, StringComparer.CurrentCultureIgnoreCase);
// names jest teraz: ["anna", "marek", "zofia"]
// LINQ OrderBy — nie modyfikuje, zwraca nową sekwencję
var sorted = names.OrderBy(n => n, StringComparer.CurrentCultureIgnoreCase).ToArray();
// names niezmienione, sorted to nowa tablica
Malejąco z Array.Sort:
Array.Sort(names, StringComparer.CurrentCultureIgnoreCase);
Array.Reverse(names); // Odwróć po sortowaniu rosnącym
Testy jednostkowe
[Fact]
public void SortNames_Ascending_IgnoresCase()
{
var result = SortNames(new[] { "Zofia", "anna", "Beata", "marek" });
Assert.Equal(new[] { "anna", "Beata", "marek", "Zofia" }, result);
}
[Fact]
public void SortNames_Descending_ReturnsReverseOrder()
{
var result = SortNames(new[] { "Zofia", "anna", "Beata" }, ascending: false);
Assert.Equal(new[] { "Zofia", "Beata", "anna" }, result);
}
[Fact]
public void SortNames_WithNulls_NullsFirst()
{
var result = SortNames(new[] { "marek", null, "anna" });
Assert.Null(result[0]);
}
[Fact]
public void SortNames_EmptyArray_ReturnsEmpty()
{
Assert.Empty(SortNames(Array.Empty<string>()));
}
Co powiedzieć na rozmowie
“Domyślne sortowanie stringów w C# to Ordinal — porównanie bajt po bajcie, gdzie wielkie litery (‘A’=65) są przed małymi (‘a’=97). Dla sortowania nazw użytkowników chcę CurrentCultureIgnoreCase żeby ‘anna’ i ‘Anna’ były traktowane jako równe i żeby polskie znaki (ą, ę) były posortowane poprawnie. LINQ.OrderBy jest bezpieczniejszy bo nie mutuje oryginalnej tablicy.”
Podsumowanie
Kluczowe decyzje: który StringComparer (zależy od kontekstu), Array.Sort (in-place) vs LINQ (nowa sekwencja). Dla danych użytkownika zawsze CurrentCulture lub CurrentCultureIgnoreCase.
2 comments
Dodaj komentarz
Musisz się zalogować, aby móc dodać komentarz.
Zamień wiedzę w umiejętności
Pobierz darmową Roadmapę .NET i ułóż takie tematy jak ten w spójną ścieżkę do pierwszej pracy.
Pobieram roadmapę →
Twój artykuł jest jak mała skarbnica wiedzy. Dzięki za podzielenie się z nam
Talentem bije każdy Twój wpis i post, twórcze myślenie nie sprawia Ci problemu, to się nazywa intelektualny most, on sprawia wielką radość każdemu odwiedzającemu.