通过两个不同类型的字段对不同模型的列表进行排序

时间:2014-05-26 21:25:26

标签: c# linq sorting interface

我有两种模式:

public class CarRent
{
    public string CarName { get; set; }
    public string SystemId { get; set; }
    public DateTime RentEndDate { get; set; }
}

public class CarPurchase
{
    public string CarName { get; set; }
    public string SystemId { get; set; }
    public decimal Mileage { get; set; }
}

我需要to combine them into one listgroup by CarName然后在每个群组中我最初需要to sortSystemId模型,但是如果模型具有相同的SystemId {1}} - to sort需要CarRent RentEndDate个模型,CarPurchase需要Mileage

我尝试了什么:

我定义了一个界面:

public interface ICarPurchaseOrdered
{
    string CarName { get; }
    string SystemId { get; }
    string Order { get; }
}

并让我的模型实现它,Order属性只返回二阶标准的字符串表示,然后我定义了一个视图模型:

public class GroupedCardList
{
    public string CarName { get; set; }
    public IEnumerable<ICarPurchaseOrdered> Cars { get; set; }
}

然后我有一个只对我的模型进行分组的石斑鱼:

public class CarGrouper
{
    IEnumerable<GroupedCardList> Group(IEnumerable<ICarPurchaseOrdered> cars)
    {
        return cars.GroupBy(c => c.CarName)
                   .OrderBy(c => c.Key)
                   .Select(c => new GroupedCardList()
                   {
                       CarName = c.Key,
                       Cars = c.OrderBy(n => n.SystemId)
                               .ThenBy(n => n.Order)
                   });
    }
}

但它不能正常工作,因为它会对字符串进行排序,我会在使用Milage=1200的汽车之前使用Milage=90购买汽车。

我知道这个例子有点做作,但它完美地代表了我现在所拥有的问题。请给我一些建议。

3 个答案:

答案 0 :(得分:2)

一种方法是实现自定义IComparer。如果您提取公共基类:

public class Car
{
    public string CarName { get; set; }
    public string SystemId { get; set; }
}

public class CarRent : Car
{
    public DateTime RentEndDate { get; set; }
}

public class CarPurchase : Car
{
    public decimal Mileage { get; set; }
}

然后IComparer<Car>实现可能如下所示:

public class CarComparer : IComparer<Car>
{
    public int Compare(Car x, Car y)
    {
        // compare by system id first
        var order = string.Compare(x.SystemId, y.SystemId);
        if (order != 0)
            return order;

        // try to cast both items as CarRent
        var xRent = x as CarRent;
        var yRent = y as CarRent;
        if (xRent != null && yRent != null)
            return DateTime.Compare(xRent.RentEndDate, yRent.RentEndDate);

        // try to cast both items as CarPurchase
        var xPurc = x as CarPurchase;
        var yPurc = y as CarPurchase;
        if (xPurc != null && yPurc != null)
            return decimal.Compare(xPurc.Mileage, yPurc.Mileage);

        // now, this is awkward
        return 0;
    }
}

然后,您可以将比较器实例传递给List.SortEnumerable.OrderBy

答案 1 :(得分:1)

您可以使用int.Parse并订购整数而不是字符串

c.OrderBy(n => n.SystemId)
  .ThenBy(n => int.Parse(n.Order))

答案 2 :(得分:0)

用于订购(然后)by的ICarPurchaseOrdered.Order是一个字符串类型;因此,为什么按字母顺序排序。

我建议将ICarPurchaseOrdered.Order的类型更改为object, 所以Orderby can use the underlying object (either DateTime or Decimal`)可以订购。

**更新: 试试这个

c.OrderBy(n => n.SystemId)
 .ThenBy(n => n.GetType())
 .ThenBy(n => n.Order);