Quiero ordenar una lista de cadenas, pero una cadena en la lista siempre debe estar al final y no ordenada. ¿Cuál es la forma más sencilla de hacer esto con LINQ?

//should be ordered in:  a,b,u,z, last:
List<string> l = {"z","u","last","b","a"}; 

No hay un método de adición o algo en LINQ, ¿verdad?

0
rawan mansour 11 jul. 2021 a las 13:04

3 respuestas

La mejor respuesta

Puede usar .Concat() para agregar la cadena que desea al final o usar .OrderBy() para colocar su cadena al final mientras deja todas las demás en el frente y usar .ThenBy() después para ordenar Los artículos. .ThenBy() se aplicará cuando los pedidos anteriores proporcionen grupos de artículos que se consideran iguales.

var list = new List<string> { "z", "u", "last", "b", "a" };
var result = list
    .OrderBy(item => item == "last" ? 1 : 0)
    .ThenBy(item => item);

O en lugar de ordenar

var list = new List<string> { "z", "u", "last", "b", "a" };
list.Sort((left, right) => left == "last" ? 1 : right == "last" ? -1 : string.Compare(left, right));

Usando .Concat()

var list = new List<string> { "z", "u", "last", "b", "a" };
var result = list
    .Where(item => item != "last")
    .OrderBy(item => item)
    .Concat(Enumerable.Repeat("last", 1));
1
Andrei15193 11 jul. 2021 a las 10:27

Actualizar

Me acabo de dar cuenta de que el OP significaba el valor "último" y no el último elemento. En este caso, sería mucho más fácil con

var result = l.OrderBy(x => string.Equals(x,"last")).ThenBy(x => x);

Tenga en cuenta que lo anterior requeriría ordenar dos veces. También puede definir un Comparador personalizado para usar con OrderBy, y allí omitiendo múltiples OrderBy

public class LastSkipComparer<T> : IComparer<T> where T : IComparable<T>
{
    private Func<T,bool> _selector;
    public LastSkipComparer(Func<T,bool> selector)
    {
        _selector = selector;
    }

    public int Compare(T instanceA, T instanceB)
    {
        if(_selector(instanceA)) return 1;
        if(_selector(instanceB)) return -1;
        return instanceA.CompareTo(instanceB);
    }
}

Ahora puedes ordenar como,

var result = l.OrderBy(x=> x,
               new LastSkipComparer<string>((val)=> string.Equals(val,"last")));

Salida de muestra

enter image description here

Respuesta inicial

Para ordenar todos los elementos, excepto el último, puede usar SkipLast, luego ordenar el resto, seguido de agregar el último elemento nuevamente. Por ejemplo,

List<string> l = new[] {"z","u","last","b","a"}.ToList();
var result = l.SkipLast(1).OrderBy(x=>x).Append(l.Last());

SkipLast: Devuelve una nueva colección enumerable que contiene los elementos de la fuente con los últimos elementos de recuento de la colección fuente omitidos.

Enumerable.Append : Agrega un valor al final de la secuencia.

Tenga en cuenta que SkipLast requiere .NET (5.0, 6.0 Preview 3) o .NET Core (2.0, 2.1, 2.2, 3.0, 3.1) o .NET Standard 2.1

Salida de muestra

enter image description here

2
Anu Viswan 11 jul. 2021 a las 11:14

Probar esto

List<string> l = new List<string>{ "z", "u", "last", "b", "a" };

var k = l.Where(x=>x!="last").OrderBy(x=>x).Append("last");
1
mjwills 11 jul. 2021 a las 10:30