在C#Linq中合并两个不同的具有排序条件的列表



所以我想从两个不同的列表中加入,没有任何键,并对该列表排序一些条件。

我有这样的Class

public class DataA
{
public string Data { get; set; }
public int Order { get; set; }
public DateTime CreatedOn { get; set; }
}
public class DataB
{
public string Data { get; set; }
public int Order { get; set; }
public DateTime CreatedOn { get; set; }
}

列表如下:

var listDataA = new List<DataA> 
{ 
new DataA { Data = "data a 1", Order = 1, CreatedOn = new DateTime(2020, 11, 12, 00, 00, 00) },
new DataA { Data = "data a 2", Order = 2, CreatedOn = new DateTime(2020, 11, 13, 00, 00, 00) },
new DataA { Data = "data a 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 16, 00, 00) },
new DataA { Data = "data a 6", Order = 6, CreatedOn = new DateTime(2020, 11, 15, 00, 00, 00) },
new DataA { Data = "data a 7", Order = 7, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
};
var listDataB = new List<DataB> 
{
new DataB { Data = "data b 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 14, 00, 00) },
new DataB { Data = "data b 8", Order = 8, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
};

我想根据每个其他Order属性对列表进行排序,如果Order值相同,它将检查CreatedOn属性。所以数据看起来是这样的:

[
{ Data = "data a 1", Order = 1, CreatedOn = new DateTime(2020, 11, 12, 00, 00, 00) },
{ Data = "data a 2", Order = 2, CreatedOn = new DateTime(2020, 11, 13, 00, 00, 00) },
{ Data = "data b 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 14, 00, 00) },
{ Data = "data a 5", Order = 5, CreatedOn = new DateTime(2020, 11, 14, 16, 00, 00) },
{ Data = "data a 6", Order = 6, CreatedOn = new DateTime(2020, 11, 15, 00, 00, 00) },
{ Data = "data a 7", Order = 7, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) },
{ Data = "data b 8", Order = 8, CreatedOn = new DateTime(2020, 11, 16, 00, 00, 00) }
]

我怎么能在林克做到这一点?

真的,我认为你最好为这些类定义一个接口,其中提到你想要使用的公共部分

interface IDataX
{
int Order { get; set; }
DateTime CreatedOn { get; set; }
}
public class DataA: IDataX ...
public class DataB: IDataX ...

然后你可以像一样

var output = listDataA.Cast<IDataX>().Concat(listDataB).OrderBy(d => d.Order).ThenBy(d => d.CreatedOn);

由于Data对两者都是通用的,您也可以将其添加到接口中,然后您可以使用IDataX中的Data,而不必具体知道下面的对象是DataA还是DataB。


如果你反对这一点(也反对为a/B创建一个具有公共属性Order/Created..的父类的类似想法(,你可能必须投影到某个公共持有者(它同样可以是匿名的,但这里不是为了举例(:

class Holder{
public int Order { get; set; }
public DateTime CreatedOn { get; set; }
public object OriginalData { get; set; }
}

和凹入的投影。。

listA
.Select(a => new Holder { Order = a.Order, CreatedOn = a.CreatedOn, OriginalData = a})
.Concat(
listB.Select(b => new Holder { Order = b.Order, CreatedOn = b.CreatedOn, OriginalData = b})
).OrderBy(x => x.Order).ThenBy(x => x.CreatedOn)

然后当你想使用OriginalData时,它会被抛出。(if(x.OriginalData is DataA a) ... else if(x.OriginalData is DataB b)有点……(

就我个人而言,我肯定会利用某种多态性来实现

最新更新