TOC

This article has been localized into Portuguese by the community.

LINQ:

Organizando dados: os métodos OrderBy() & ThenBy()

Portanto, agora que aprendemos no artigo anterior como obter dados da fonte de dados com o LINQ e filtrá-los com o método Where(), a próxima etapa poderia ser classificar os dados. Usamos listas de objetos, numéricos ou baseados em, e. uma classe User, então a ordem em que os itens foram colocados foi a mesma ordem em que eles foram adicionados à lista. No entanto, como falamos anteriormente, sua fonte de dados para operações LINQ pode ser um documento XML ou um banco de dados. Portanto, a capacidade de ordenar corretamente os dados, uma vez que temos os dados de que precisamos, é crucial. Felizmente para nós, o LINQ tem vários métodos fáceis de usar para ordenar dados - vamos tentar um exemplo básico primeiro:

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);

Isso foi fácil, certo? Basta chamar o método OrderBy() e fornecer o objeto ou o membro do objeto para classificar e uma lista classificada será retornada. E é claro que você pode fazer isso com a mesma facilidade com strings, como veremos no próximo exemplo, mas vamos colocar os itens em ordem decrescente (da maior para a menor/de Z para 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);

Fazemos exatamente a mesma coisa de antes, exceto pelo fato de usarmos o método OrderByDescending() em vez do método OrderBy(). Mas é claro que você pode obter a sua lista de números inteiros e seqüências de caracteres facilmente classificados - isso é um pedaço de bolo! No entanto, graças ao LINQ, é muito fácil classificar objetos mais complexos. Aqui está um exemplo:

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; }
}
    }
}

Este é obviamente um exemplo mais completo, com a classe User incluída e a lista de usuários inicializada, mas como você pode ver, a classificação atual ainda é muito curta e precisa: Ao chamar o método OrderBy(), nós apenas fornecemos nome do parâmetro e, em seguida, use esse parâmetro para acessar a propriedade Age dos objetos User. O resultado é uma lista perfeitamente ordenada por idade! Mas e se quisermos encomendar por mais de uma propriedade?

ThenBy() e ThenByDescending()

No exemplo acima, classificamos a lista de usuários por idade, mas e se houver vários usuários da mesma idade? Um cenário bem comum, mesmo em nosso pequeno exemplo - imagine que Jane e John são da mesma idade e seus filhos são gêmeos. Nesse caso, seria prático controlar a ordem mesmo depois de a origem dos dados ter sido organizada por idade. Para isso, podemos usar os métodos ThenBy() e ThenByDescending() . Eles fazem exatamente o que o nome indica: controle a ordem após a classificação inicial. Podemos usar isso para obter a lista de usuários classificados, primeiro por idade e depois alfabeticamente por nome:

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");

Muito simples, mas muito eficaz! Você pode até encadear várias chamadas de método ThenBy(), caso seus dados sejam mais complexos que os dados de nosso caso de teste. E, claro, você pode misturar e combinar os métodos OrderBy(), OrderByDescending(), ThenBy() e ThenByDescending() da maneira que você precisa:

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");

Nós estamos usando majoritariamente a sintaxe baseada em métodos do LINQ neste tutorial, mas como sempre, eu vou usar um dos exemplos neste artigo e mostrar a você como ele ficaria com a sintaxe de consulta - aqui está o último exemplo, incluindo uma versão de Sintaxe de consulta do 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();

Como você pode ver, a sintaxe é ligeiramente diferente - a direção (ascendente ou descendente) é especificada diretamente após o campo para ordenar por (ascendente é, na verdade, implícito, mas eu o incluí para mostrar a diferença). Além disso, não há "ThenBy" - em vez disso, você apenas separa várias instruções de classificação com uma vírgula. Claro que, no final, ambas as consultas lhe darão o mesmo resultado.

Resumo

Usando os métodos OrderBy() e ThenBy() (assim como suas contrapartes "descendentes"), você pode facilmente organizar seus dados da maneira que quiser. E lembre-se, assim como qualquer outro método LINQ, a fonte de dados real não é manipulada - em vez disso, você obtém uma cópia ordenada da fonte de dados original, com a qual você pode trabalhar.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!