Operadores de LINQ: Ordering

Tabla de contenidos:

OrderBy

El operador OrderBy ordena una secuencia de forma ascendente dada una clave.

Código necesario para los ejemplos:

Una clase persona:

public class Persona
{
    public string Nombre { get; set; }
    public int Edad {get; set; }

    public Persona(string nombre, int edad)
    {
        Nombre = nombre;
        Edad = edad;
    }
}

Una lista de personas:

List<Persona> personas = new List<Persona>
				 {
					 new Persona("Rodriguez, Jesús", 24),
					 new Persona("Perez, Juan", 15),
					 new Persona("García, Javier", 45),
					 new Persona("Toledo, María", 37)
				 };

Un comparador personalizado:

public class OrdenaNombre : IComparer<string>
{
	public int Compare(string x, string y)
	{
		string nombreX = x.Split()[1];
		string nombreY = y.Split()[1];

		return nombreX.CompareTo(nombreY);
	}
}

Volver al operador OrderBy

OrderBy estándar:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
	this IEnumerable<TSource> source,
	Func<TSource, TKey> keySelector
)

OrderBy toma como parámetro la clave que se usará para ordenar la secuencia. Devuelve una enumeración ordenada.

Por ejemplo, si queremos ordenar la lista de personas por el nombre, usaríamos este código:

IEnumerable<Persona> ascendente = personas.OrderBy(persona => persona.Nombre);

La clave en este caso es la propiedad Nombre del elemento de la secuencia.

Como alternativa, podemos usar la sintaxis de los query expressions:

IEnumerable<Persona> ascendente = from persona in personas
								  orderby persona.Nombre
								  select persona;

El resultado sería:

Nombre=García, Javier Edad=45
Nombre=Perez, Juan Edad=15
Nombre=Rodriguez, Jesús Edad=24
Nombre=Toledo, María Edad=37

Volver al operador OrderBy

OrderBy + Comparador personalizado:

public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
	this IEnumerable<TSource> source,
	Func<TSource, TKey> keySelector,
	IComparer<TKey> comparer
)

Aquí además de la clave que usaremos para ordenar, usaremos un comparador personalizado.

Por ejemplo, queremos ordenar otra vez usando la propiedad Nombre pero en este caso en vez de ordenar por el apellido vamos a ordenar por el nombre en sí.

Para ello cogemos el comparador OrdenaNombre que he adjuntado en el código que necesitamos para trabajar con este operador, con ello escribimos:

IEnumerable<Persona> ascendente = personas.OrderBy(persona => persona.Nombre, new OrdenaNombre());

El comparador extraerá el nombre de cada propiedad y los comparará.

El resultado es:

Nombre=García, Javier Edad=45
Nombre=Rodriguez, Jesús Edad=24
Nombre=Perez, Juan Edad=15
Nombre=Toledo, María Edad=37

Volver a la tabla de contenidos

OrderByDescending

El operador OrderByDescending ordena una secuencia de forma descendente dada una clave.

Código necesario para los ejemplos:

Una clase persona:

public class Persona
{
    public string Nombre { get; set; }
    public int Edad {get; set; }

    public Persona(string nombre, int edad)
    {
        Nombre = nombre;
        Edad = edad;
    }
}

Una lista de personas:

List<Persona> personas = new List<Persona>
				 {
					 new Persona("Rodriguez, Jesús", 24),
					 new Persona("Perez, Juan", 15),
					 new Persona("García, Javier", 45),
					 new Persona("Toledo, María", 37)
				 };

Un comparador personalizado:

public class OrdenaNombre : IComparer<string>
{
	public int Compare(string x, string y)
	{
		string nombreX = x.Split()[1];
		string nombreY = y.Split()[1];

		return nombreX.CompareTo(nombreY);
	}
}

Volver al operador OrderByDescending

OrderByDescending estándar:

public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
	this IEnumerable<TSource> source,
	Func<TSource, TKey> keySelector
)

OrderByDescending toma como parámetro la clave que se usará para ordenar la secuencia (de forma descendente). Devuelve una enumeración ordenada.

Por ejemplo, si queremos ordenar la lista de personas por el nombre (de forma descendente), usaríamos este código:

IEnumerable<Persona> descendente = personas.OrderByDescending(persona => persona.Nombre);

La clave en este caso es la propiedad Nombre del elemento de la secuencia.

Como alternativa, podemos usar la sintaxis de los query expressions:

IEnumerable<Persona> descendente = from persona in personas
								   orderby persona.Nombre descending
								   select persona;

El resultado sería:

Nombre=Toledo, María Edad=37
Nombre=Rodriguez, Jesús Edad=24
Nombre=Perez, Juan Edad=15
Nombre=García, Javier Edad=45

Volver al operador OrderByDescending

OrderByDescending + Comparador personalizado:

public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
	this IEnumerable<TSource> source,
	Func<TSource, TKey> keySelector,
	IComparer<TKey> comparer
)

Aquí además de la clave que usaremos para ordenar, usaremos un comparador personalizado.

Por ejemplo, queremos ordenar otra vez usando la propiedad Nombre pero en este caso en vez de ordenar por el apellido vamos a ordenar por el nombre en sí.

Para ello cogemos el comparador OrdenaNombre que he adjuntado en el código que necesitamos para trabajar con este operador, con ello escribimos:

IEnumerable<Persona> descendente = personas.OrderByDescending(persona => persona.Nombre, new OrdenaNombre());

El comparador extraerá el nombre de cada propiedad y los comparará.

El resultado es:

Nombre=Toledo, María Edad=37
Nombre=Perez, Juan Edad=15
Nombre=Rodriguez, Jesús Edad=24
Nombre=García, Javier Edad=45

Volver a la tabla de contenidos

Reverse

El operador Reverse invierte una secuencia.

Código necesario para los ejemplos:

Una lista de cadenas representando números:

List<string> numeros = new List<string> {"Uno", "Dos", "Tres", "Cuatro", "Cinco"};

Volver al operador Reverse

Reverse:

public static IEnumerable<TSource> Reverse<TSource>(
	this IEnumerable<TSource> source
)

Este operador no toma ningún parámetro cuando lo usas en una secuencia (ya que el parámetro que empieza por this indice que es un método de extensión).

Cuando lo usas como un método de extensión en una secuencia, modifica la misma secuencia en sí pero no devuelve nada.

Por ejemplo:

numeros.Reverse();

Eso le daría la vuelta a la lista de números directamente.

O sea:

Cinco
Cuatro
Tres
Dos
Uno

Volver a la tabla de contenidos

ThenBy

El operador ThenBy toma una enumeración ordenada y le hace una ordenación adicional usando otra clave.

Código necesario para los ejemplos:

Una clase persona:

public class Persona
{
    public string Nombre { get; set; }
    public int Edad {get; set; }

    public Persona(string nombre, int edad)
    {
        Nombre = nombre;
        Edad = edad;
    }
}

Una lista de personas:

List<Persona> personas = new List<Persona>
				 {
					 new Persona("Rodriguez, Jesús", 24),
					 new Persona("Rodriguez, Jesús", 15),
					 new Persona("Perez, Juan", 15),
					 new Persona("García, Javier", 24),
					 new Persona("Toledo, María", 37)
				 };

Un comparador personalizado:

public class OrdenaNombre : IComparer<string>
{
	public int Compare(string x, string y)
	{
		string nombreX = x.Split()[1];
		string nombreY = y.Split()[1];

		return nombreX.CompareTo(nombreY);
	}
}

Volver al operador ThenBy

ThenBy estándar:

public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(
	this IOrderedEnumerable<TSource> source,
	Func<TSource, TKey> keySelector
)

El operador ThenBy toma como argumento la clave que se usará para la ordenación adicional. Devuelve la enumeración ordenada.

Por ejemplo, queremos ordenar la lista de personas primero por su nombre y como ordenación adicional, la edad:

IEnumerable<Persona> dobleOrdenación = personas.OrderBy(persona => persona.Nombre)
										.ThenBy(persona => persona.Edad);

Estamos usado lo que se llama Encadenar operadores esto quiere decir:

Llamamos a OrderBy desde personas, OrderBy devuelve un IOrderedEnumerable (una enumeración ordenada).
ThenBy es un método de extensión de dicho IOrderedEnumerable así que a eso le aplicamos ThenBy.

Dicho de otra forma, ordenamos primero por nombre y luego ordenamos por edad.

También podemos hacer esto usando una query expression:

IEnumerable<Persona> dobleOrdenacion = from persona in personas
                       orderby persona.Nombre , persona.Edad
                       select persona;

En ambos casos, el resultado es:


Nombre=García, Javier Edad=24
Nombre=Perez, Juan Edad=15
Nombre=Rodriguez, Jesús Edad=15
Nombre=Rodriguez, Jesús Edad=24
Nombre=Toledo, María Edad=37

Volver al operador ThenBy

ThenBy + Comparador personalizado:

public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(
	this IOrderedEnumerable<TSource> source,
	Func<TSource, TKey> keySelector,
	IComparer<TKey> comparer
)

Aquí además de la clave, recibimos una instancia de un comparador personalizado.

Vamos a ordenar primero por Edad (de forma descendente) y luego por Nombre pero usando el nombre y no el apellido para ordenar. Para ello usaremos una instancia del comparador adjunto con el código:

IEnumerable<Persona> dobleOrdenacion = personas.OrderByDescending(persona => persona.Edad)
				.ThenBy(persona => persona.Nombre, new OrdenaNombre());

Como puedes ver, ThenBy trabaja con una enumeración ordenada, pero le da igual si está ordenada ascendentemente o descendentemente.

El resultado es:

Nombre=Toledo, María Edad=37
Nombre=García, Javier Edad=24
Nombre=Rodriguez, Jesús Edad=24
Nombre=Rodriguez, Jesús Edad=15
Nombre=Perez, Juan Edad=15

Volver a la tabla de contenidos

ThenByDescending

El operador ThenByDescending toma una enumeración ordenada y le hace una ordenación adicional descendente usando otra clave.

Código necesario para los ejemplos:

Una clase persona:

public class Persona
{
    public string Nombre { get; set; }
    public int Edad {get; set; }

    public Persona(string nombre, int edad)
    {
        Nombre = nombre;
        Edad = edad;
    }
}

Una lista de personas:

List<Persona> personas = new List<Persona>
				 {
					 new Persona("Rodriguez, Jesús", 24),
					 new Persona("Rodriguez, Jesús", 15),
					 new Persona("Perez, Juan", 15),
					 new Persona("García, Javier", 24),
					 new Persona("Toledo, María", 37)
				 };

Un comparador personalizado:

public class OrdenaNombre : IComparer<string>
{
	public int Compare(string x, string y)
	{
		string nombreX = x.Split()[1];
		string nombreY = y.Split()[1];

		return nombreX.CompareTo(nombreY);
	}
}

Volver al operador ThenByDescending

ThenByDescending estándar:

public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(
	this IOrderedEnumerable<TSource> source,
	Func<TSource, TKey> keySelector
)

El operador ThenByDescending toma como argumento la clave que se usará para la ordenación adicional (que será descendiente). Devuelve la enumeración ordenada.

Por ejemplo, queremos ordenar la lista de personas primero por su nombre (ascendente) y como ordenación adicional, la edad (descendente):

IEnumerable<Persona> dobleOrdenacion = personas.OrderBy(persona => persona.Nombre)
					.ThenByDescending(persona => persona.Edad);

Estamos usado lo que se llama Encadenar operadores esto quiere decir:

Llamamos a OrderBy desde personas, OrderBy devuelve un IOrderedEnumerable (una enumeración ordenada).
ThenByDescending es un método de extensión de dicho IOrderedEnumerable así que a eso le aplicamos ThenByDescending.

Dicho de otra forma, ordenamos primero por nombre y luego ordenamos por edad.

También podemos hacer esto usando una query expression:

IEnumerable<Persona> dobleOrdenacion = from persona in personas
									   orderby persona.Nombre, persona.Edad descending
									   select persona;

En ambos casos, el resultado es:

Nombre=García, Javier Edad=24
Nombre=Perez, Juan Edad=15
Nombre=Rodriguez, Jesús Edad=24
Nombre=Rodriguez, Jesús Edad=15
Nombre=Toledo, María Edad=37

Volver al operador ThenByDescending

ThenByDescending + Comparador personalizado:

public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(
	this IOrderedEnumerable<TSource> source,
	Func<TSource, TKey> keySelector,
	IComparer<TKey> comparer
)

Aquí además de la clave, recibimos una instancia de un comparador personalizado.

Vamos a ordenar primero por Edad y luego por Nombre (Descendente) pero usando el nombre y no el apellido para ordenar. Para ello usaremos una instancia del comparador adjunto con el código:

IEnumerable<Persona> dobleOrdenacion = personas.OrderBy(persona => persona.Edad)
				.ThenByDescending(persona => persona.Nombre, new OrdenaNombre());

El resultado es:

Nombre=Perez, Juan Edad=15
Nombre=Rodriguez, Jesús Edad=15
Nombre=Rodriguez, Jesús Edad=24
Nombre=García, Javier Edad=24
Nombre=Toledo, María Edad=37

Volver a la tabla de contenidos

Tags:

Un comentario

Dejar un comentario