This article has been localized into Czech by the community.
Řazení dat: Metody OrderBy() a ThenBy()
Protože jsme se v předchozím článku naučili, jak získat data ze zdroje dat pomocí LINQ a filtrovat je pomocí metody Where(), dalším krokem by mohlo být seřazení dat. Používali jsme seznamy objektů, buď numerických, nebo například na základě třídy User, takže pořadí, ve kterém jsme získali položky, bylo stejné jako pořadí, ve kterém byly do seznamu přidány. Nicméně, jak jsme již dříve hovořili, zdrojem dat pro operace LINQ může být stejně dobře XML dokument nebo databáze. Proto je schopnost správně řadit data zásadní. Naštěstí pro nás má LINQ několik snadno použitelných metod pro řazení dat - vyzkoušejme si nejprve základní příklad:
List<int> numbers = new List<int>()
{
1, 7, 2, 61, 14
};
List<int> sortedNumbers = numbers.OrderBy(number => number).ToList();
foreach (int number in sortedNumbers)
Console.WriteLine(number);
To bylo snadné, že? Stačí zavolat metodu OrderBy() a dodat objekt nebo člena objektu, podle kterého se má řadit, a bude vrácen seřazený seznam. A samozřejmě to lze udělat stejně snadno i se řetězci, jak uvidíme v příštím příkladu, ale získáme položky v sestupném pořadí (od největšího k nejmenšímu/od Z k A):
List<string> cityNames = new List<string>()
{
"Amsterdam", "Berlin", "London", "New York"
};
List<string> sortedCityNames = cityNames.OrderByDescending(city => city).ToList();
foreach (string cityName in sortedCityNames)
Console.WriteLine(cityName);
Děláme přesně to samé jako předtím, pouze používáme metodu OrderByDescending() namísto metody OrderBy(). Ale samozřejmě, že můžete získat svůj seznam čísel a řetězců snadno seřazený - to je hračka! Díky LINQ je ale prakticky stejně snadné řadit i složitější objekty. Zde je příklad:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqOrder2
{
class Program
{
static void Main(string[] args)
{
List<User> listOfUsers = new List<User>()
{
new User() { Name = "John Doe", Mail = "john@doe.com", Age = 42 },
new User() { Name = "Jane Doe", Mail = "jane@doe.com", Age = 34 },
new User() { Name = "Joe Doe", Mail = "joe@doe.com", Age = 8 },
new User() { Name = "Another Doe", Mail = "another@doe.com", Age = 15 },
};
List<User> usersByAge = listOfUsers.OrderBy(user => user.Age).ToList();
foreach (User user in usersByAge)
Console.WriteLine(user.Name + ": " + user.Age + " years");
}
class User
{
public string Name { get; set; }
public string Mail { get; set; }
public int Age { get; set; }
}
}
}
Toto je samozřejmě komplexnější příklad, kde je zahrnuta třída User a seznam uživatelů je inicializován, ale jak můžete vidět, samotné řazení je stále velmi stručné a přesné: Při volání metody OrderBy() stále jen poskytneme název parametru a poté použijeme tento parametr k přístupu k vlastnosti Age objektů User. Výsledkem je dokonale seřazený seznam podle věku! Ale co když chceme řadit podle více než jedné vlastnosti?
ThenBy() a ThenByDescending()
Ve výše uvedeném příkladu jsme seřadili seznam uživatelů podle jejich věku, ale co když by několik uživatelů mělo stejný věk? Docela běžný scénář, i v našem malém příkladu - představte si, že Jane a John jsou stejně staří a jejich děti jsou dvojčata. V takovém případě by bylo praktické ovládat pořadí i po tom, co byl zdroj dat seřazen podle věku. Pro to můžeme použít metody ThenBy() a ThenByDescending(). Dělají přesně to, co název naznačuje: Ovládají pořadí po počátečním seřazení. Můžeme to využít k tomu, aby byl seznam uživatelů seřazen nejprve podle věku a poté abecedně podle jména.
List<User> listOfUsers = new List<User>()
{
new User() { Name = "John Doe", Mail = "john@doe.com", Age = 42 },
new User() { Name = "Jane Doe", Mail = "jane@doe.com", Age = 42 },
new User() { Name = "Joe Doe", Mail = "joe@doe.com", Age = 8 },
new User() { Name = "Jenna Doe", Mail = "another@doe.com", Age = 8 },
};
List<User> sortedUsers = listOfUsers.OrderBy(user => user.Age).ThenBy(user => user.Name).ToList();
foreach (User user in sortedUsers)
Console.WriteLine(user.Name + ": " + user.Age + " years");
Docela jednoduché, ale velmi účinné! Můžete dokonce řetězit více volání metody ThenBy(), pokud jsou vaše data složitější než data z našeho testovacího případu. A samozřejmě můžete kombinovat metody OrderBy(), OrderByDescending(), ThenBy() a ThenByDescending() jakkoli potřebujete.
List<User> sortedUsers = listOfUsers.OrderBy(user => user.Age).ThenByDescending(user => user.Name).ToList();
foreach (User user in sortedUsers)
Console.WriteLine(user.Name + ": " + user.Age + " years");
Ve většině případů používáme v tomto tutoriálu syntaxi založenou na metodách LINQ, ale jako vždy vezmu jeden z příkladů v článku a ukážu vám, jak by to vypadalo se syntaxí dotazu LINQ - zde je poslední příklad, včetně verze se syntaxí dotazu LINQ:
// Method syntax
List<User> sortedUsers = listOfUsers.OrderBy(user => user.Age).ThenByDescending(user => user.Name).ToList();
// Query syntax
List<User> sortedUsersQ = (from user in listOfUsers orderby user.Age ascending, user.Name descending select user).ToList();
Jak vidíte, syntaxe je mírně odlišná - směr (vzestupně nebo sestupně) je specifikován přímo po poli, podle kterého se řadí (vzestupně je ve skutečnosti implicitní, ale zahrnul jsem to, abych vám ukázal rozdíl). Také není žádný "ThenBy" - místo toho jen oddělíte více instrukcí řazení čárkou. Samozřejmě, že na konci oba dotazy dají stejný výsledek.
Shrnutí
Pomocí metod OrderBy() a ThenBy() (stejně jako jejich "sestupných" protějšků) můžete snadno seřadit svá data přesně tak, jak chcete. A pamatujte, stejně jako u jakékoli jiné metody LINQ, původní zdroj dat není manipulován - místo toho získáte seřazenou kopii původního zdroje dat, se kterou můžete pracovat.