LINQ OrderBy值等于另一个属性

时间:2017-01-25 15:39:40

标签: c# .net linq sorting

对象:

public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public bool? Main { get; set; } 

我有一个我想要排序的项目列表。

首先,它将是具有Main == true属性的项目,EndDate为null

然后我希望按开始日期降序项目,如果开始日期相等,则按结束日期降序排序

这是我的尝试:

items.OrderByDescending(p => p.Main == true && p.EndDate == null)
                           .ThenByDescending(p => p.StartDate)
                           .ThenByDescending(p => p.EndDate).ToList();

实际上并不是我期望的结果,如果值等于其他值之后的排序,您在排序时是否有条件?

3 个答案:

答案 0 :(得分:2)

构建结果集并连接它们。

var maintrue = items.Where(p => p.Main == true && p.EndDate == null);
var others = items.Where(i => !maintrue.Contains(i))
                  .OrderByDescending(p => p.StartDate)
                  .ThenByDescending(p => p.EndDate);

var result = maintrue.Concat(others).ToList();

答案 1 :(得分:1)

我不确定它是否有点矫枉过正,但您可以使用自定义比较器:

class ObjComparer
    : IComparer<Obj>
{
    public int Compare(Obj x, Obj y)
    {
        int compare = CompareByProperties(x, y);
        if (compare == 0)
        {
            compare = CompareByDate(x.StartDate, y.StartDate);
            if (compare == 0)
            {
                compare = CompareByDate(x.EndDate, y.EndDate);
            }
        }
        return compare;
    }

    static int CompareByProperties(Obj o1, Obj o2)
    {
        return MainIsTrueAndEndDateIsNull(o1) ?
                (MainIsTrueAndEndDateIsNull(o2) ? 0 : 1) :
                (MainIsTrueAndEndDateIsNull(o2) ? -1 : 0);
    }

    static bool MainIsTrueAndEndDateIsNull(Obj o)
    {
        return o.Main.Value && o.EndDate == null;
    }

    static int CompareByDate(DateTime? d1, DateTime? d2)
    {
        return d1 == d2 ? 0 : (d1 > d2 ? 1 : -1);
    }
}

简单地用作:

var orderedItems = items.OrderBy(o => o, new ObjComparer());

答案 2 :(得分:1)

您必须对数据进行分组。试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;



namespace ConsoleApplication43
{
    class Program
    {

        static void Main(string[] args)
        {
            List<MyDate> dates = new List<MyDate>() {
                new MyDate() { Main = true, StartDate = DateTime.Parse("1/1/17"), EndDate = DateTime.Parse("1/3/17") },
                new MyDate() { Main = true,                                       EndDate = DateTime.Parse("1/4/17") },
                new MyDate() { Main = true, StartDate = DateTime.Parse("1/2/17"), EndDate = DateTime.Parse("1/5/17") },
                new MyDate() { Main = true, StartDate = DateTime.Parse("1/3/17"), EndDate = DateTime.Parse("1/6/17") },
                new MyDate() { Main = false, StartDate = DateTime.Parse("1/4/17"), EndDate = DateTime.Parse("1/7/17") },
                new MyDate() { Main = true,                                       EndDate = DateTime.Parse("1/8/17") },
                new MyDate() { Main = true, StartDate = DateTime.Parse("1/4/17"), EndDate = DateTime.Parse("1/9/17") },
                new MyDate() { Main = false, StartDate = DateTime.Parse("1/5/17"), EndDate = DateTime.Parse("1/10/17") },
                new MyDate() { Main = false, StartDate = DateTime.Parse("1/5/17"), EndDate = DateTime.Parse("1/11/17") },
                new MyDate() { Main = false, StartDate = DateTime.Parse("1/5/17"), EndDate = DateTime.Parse("1/12/17") }
            };

            var results = dates.Select(p => new { key = p.Main == true && p.EndDate == null, date = p })
                .GroupBy(x => x.key).Select(y => y.GroupBy(z => z.date.StartDate).Select(a => a.OrderBy(b => b.date.EndDate)))
                    .SelectMany(y => y).SelectMany(x => x).Select(p => p.date).ToList();

            foreach(MyDate result in results)
            {
                Console.WriteLine("{0},{1},{2}",
                    result.Main == null ? "" : result.Main == true ? "true" : "false",
                    result.StartDate.ToString(),
                    result.EndDate.ToString());
            }
            Console.ReadLine();
        }
    }
    public class MyDate
    {
        public DateTime? StartDate { get; set; }
        public DateTime? EndDate { get; set; }
        public bool? Main { get; set; } 
    }
}