顶级订单未知的订单列表

时间:2015-09-07 12:15:01

标签: c# linq sorting

要使用Linq订购列表,我们必须先调用OrderBy,然后在结果上调用ThenBy进行从属排序。

我现在处于一种我不知道顶级订购的情况。我有一份有条件应用的订单清单。

像这样:

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

因此,列表将始终按Item1排序,并有条件地按Item2和/或Item3排序。

如何在C#中实现这一目标?没有Linq的解决方案也很受欢迎。

3 个答案:

答案 0 :(得分:7)

只需使用

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

这为您提供了默认(非)排序,并允许您在之后使用ThenBy添加任意数量的其他排序。

修改

Tim指出,这确实会带来性能损失 - 似乎默认的LINQ-to-Objects提供商不够智能,无法重建排序以摆脱&#34;非订购&#34 ;。如果您的列表很小,这不是问题,但是如果它花费的时间不可忽略,那么您可能想要这么做。

例如,您可以使用辅助方法,如

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);
}

这与你正在做的完全相同,但除非您正在处理以前订购过的可枚举,否则它会去以同样的方式工作。

答案 1 :(得分:2)

使用IOrderedEnumerable代替列表和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 :(得分:-1)

您需要使用状态机,如下面的代码

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;
            }
        }
    }
}


​