Reputation: 35713
I want to order a List of strings but one string in the list should always be at the beginning and not sorted. What is the easiest way to do this with LINQ?
//should be ordered in: first, a,b,u,z:
List<string> l = {"z","u","first","b","a"};
There is no prepend method or something in LINQ, is there?
Upvotes: 21
Views: 11474
Reputation: 17058
Order by two criteria. The first criteria is based on some sort of predicate, the second on the value of the items:
[TestMethod]
public void TestMethod1()
{
var list = new[] { "z", "u", "first", "b", "a" }.OrderByPredicateFirst(s => s == "first").ToList();
Assert.AreEqual("first", list[0]);
Assert.AreEqual("a", list[1]);
Assert.AreEqual("b", list[2]);
Assert.AreEqual("u", list[3]);
Assert.AreEqual("z", list[4]);
}
public static class Extensions
{
public static IEnumerable<T> OrderByPredicateFirst<T>(this IEnumerable<T> source, Predicate<T> firsts)
{
return source
.OrderBy(s => firsts(s) ? 0 : 1)
.ThenBy(s => s);
}
}
Upvotes: 1
Reputation: 32438
l = l.OrderBy(i => i != "first").ThenBy(i => i).ToList();
The trick here is to order by whether the item in question is your special item, then order by your item as you normally would.
Since you said you want to order a list (with linq) don't forget to assign the result of the query back to the list.
You also asked about a prepend method, how about this:
l = new[] { "first" }.Concat(l).ToList();
You could easily make it an extension method:
public static class LinqExtensions
{
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> query, T item)
{
return new[] { item }.Concat(query);
}
}
called as:
l = l.Prepend("first").ToList();
Upvotes: 41
Reputation: 32481
You can use OrderBy
, ThenBy
pattern:
string[] l = { "z", "u", "first", "b", "a" };
var result = l.OrderBy(i => i != "first").ThenBy(i => i);
Upvotes: 4