List of orders where the top-level order is unknown

To order a list with Linq, we must call OrderBy first en call ThenBy for the result for subordinate orders.

Now I am in a situation where I do not know how to order the upper level before hand. I have a list of orders that should be applied conditionally.

Like this:

 var list = new List<Tuple<int, string, DateTime>>(); list.Add(new Tuple<int, string, DateTime>(1, "B", new DateTime(2020, 1, 1))); list.Add(new Tuple<int, string, DateTime>(2, "A", new DateTime(2000, 1, 1))); list.Add(new Tuple<int, string, DateTime>(3, "C", new DateTime(1900, 1, 1))); var orderedList = list; if (sortByString) { orderdedList = orderedList.ThenBy(listItem => listItem.Item2); } if (sortByDateTime) { orderedList = orderedList.ThenBy(listItem => listItem.Item3); } orderList = orderedList.ThenBy(listItem => listItem.Item1); 

Thus, the list will always be ordered by Item1 and, conditionally, by Item2 and / or Item3.

How to do it in C #? Solutions without Linq are also welcome.

+5
source share
3 answers

Just use

 var orderedItems = list.OrderBy(_ => 1); 

This gives you a default ( ThenBy ) order and allows you to add as many other orders as you want using only ThenBy .

EDIT:

As Tim pointed out, this does have a performance limitation - it seems that the default LINQ-to-provider provider is not smart enough to rebuild an order to get rid of non-ordering. This is not a problem if your list is small, but if it takes a small amount of time, you probably want to do it the hard way.

For example, you can use a helper method like

 public static IEnumerable<T> AppendOrdering<T, U>(this IEnumerable<T> @this, Func<T, U> selector) { if (@this is IOrderedEnumerable<T>) return @this.ThenBy(selector); return @this.OrderBy(selector); } 

This is not exactly the same as what you do, but if you are not working on an enumeration that was ordered earlier, it will work the same.

+7
source

Use IOrderedEnumerable instead of list and if ... else :

 IOrderedEnumerable<Tuple<int, string, DateTime>> orderedItems = null; if (sortByDateTime) orderedItems = list.OrderBy(listItem => listItem.Item3); else if (sortByString) orderedItems = list.OrderBy(listItem => listItem.Item2); orderedItems = orderedItems.ThenBy(listItem => listItem.Item1); list = orderedItems.ToList(); 
+2
source

You need to use a state machine, for example, the code below

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { enum State { One, Two, } static void Main(string[] args) { State state = State.A; switch (state) { case State.One: //Order by item one state = State.Two; break; case State.Two: //Order by item two or three state = State.One; break; } } } }​ 
-1
source

All Articles