rawan mansour
rawan mansour

Reputation: 79

Sort List except one entry with LINQ, to be at the last

I want to order a List of strings but one string in the list should always be at the last and not sorted. What is the easiest way to do this with LINQ?

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

There is no append method or something in LINQ, is there?

Upvotes: 1

Views: 1791

Answers (3)

Anu Viswan
Anu Viswan

Reputation: 18155

Update

Just realized the OP meant the value "last" and not the Last element. In this case, it would be much easier with

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

Please note the above would require sorting twice.You could also define a Custom Comparer to be used with OrderBy, and there by skipping multiple 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);
    }
}

Now You could sort as,

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

Sample Output

enter image description here

Initial Answer

To order every element, but the last, You could use use SkipLast, then Order the remaining, followed by Appending the Last Element again. For Example,

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

SkipLast : Returns a new enumerable collection that contains the elements from source with the last count elements of the source collection omitted.

Enumerable.Append : Appends a value to the end of the sequence.

Please note SkipLast require .NET(5.0, 6.0 Preview 3) Or .NET Core( 2.0, 2.1, 2.2, 3.0, 3.1) or .NET Standard 2.1

Sample Output

enter image description here

Upvotes: 2

Amit Verma
Amit Verma

Reputation: 2490

try this

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

var k = l.Where(x=>x!="last").OrderBy(x=>x).Append("last");

Upvotes: 1

Andrei15193
Andrei15193

Reputation: 705

You can use either .Concat() to add the string that you desire at the end or use .OrderBy() to place your string at the end while leaving all others in the front and use .ThenBy() afterwards to sort the items. .ThenBy() will apply when you the previous orderings provide groups of items that are considered equal.

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

Or in place sort

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

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

Upvotes: 3

Related Questions