订单列表,其中顶级订单是未知的
本文关键字:未知 单列表 列表 | 更新日期: 2023-09-27 18:11:28
要用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的解决方案
就用
var orderedItems = list.OrderBy(_ => 1);
这给了你默认的(非)排序,并允许你在使用ThenBy
之后添加尽可能多的其他排序。
正如Tim所指出的,这确实带来了性能损失——似乎默认的LINQ-to-Objects提供程序不够聪明,无法重建排序以摆脱"非排序"。如果你的列表很小,这不是一个问题,但是如果它占用了不可忽略的时间,你可能想要用困难的方式来做。
例如,您可以使用像 这样的辅助方法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);
}
这个和你做的不完全一样,但是除非你处理的是一个之前已经排序过的可枚举对象,否则它的工作方式是一样的。
使用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();
您需要使用如下代码所示的状态机
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;
}
}
}
}