如何在使用linq排序时包含null值

时间:2017-05-24 03:53:19

标签: c# linq

我有两份报告并将它们合并到一个列表中。某些项目具有空值。当我进行排序时,它会在最后移动空值。

以下是示例程序

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Report> reports = new List<Report>();

            Report[] report1 = {
                new Report{Id=10001,Date=null},
                new Report{Id=10001,Date=null},
                new Report{Id=10001,Date=Convert.ToDateTime("01/01/2017")}};


            Report[] report2 = {
                new Report{Id=10002,Date=null},
                new Report{Id=10002,Date=null},
                new Report{Id=10002,Date=Convert.ToDateTime("03/01/2017")}};


            Report[] report3 = {
                new Report{Id=10003,Date=null},
                new Report{Id=10003,Date=null},
                new Report{Id=10003,Date=Convert.ToDateTime("05/01/2017")}};


            Report[] report4 = {
                new Report{Id=10004,Date=null},
                new Report{Id=10004,Date=null},
                new Report{Id=10004,Date=Convert.ToDateTime("07/01/2017")}};

            reports.AddRange(report1);
            reports.AddRange(report2);
            reports.AddRange(report3);
            reports.AddRange(report4);


            var report5 = new List<Report>() 
            {
                new Report{Id=null,Date=Convert.ToDateTime("02/01/2017")},
                new Report{Id=null,Date=Convert.ToDateTime("04/01/2017")},
                new Report{Id=null,Date=Convert.ToDateTime("06/01/2017")},
            };

            reports.AddRange(report5);

            foreach (var report in reports.OrderByDescending(x => x.Date))
            {
                Console.WriteLine("ID = " + report.Id + " " + "Date = " + report.Date);
            }

            Console.ReadKey();
        }
    }

    class Report
    {
        public int? Id { get; set; }
        public DateTime? Date { get; set; }
    }
}

应根据日期进行排序,不应跳过/移动报告列表的空值。输出应如下。

ID = 10004 Date = 
ID = 10004 Date = 
ID = 10004 Date = 07/01/2017
ID =     Date = 06/01/2017
ID = 10003 Date = 
ID = 10003 Date = 
ID = 10003 Date = 05/01/2017
ID =     Date = 04/01/2017
ID = 10002 Date = 
ID = 10002 Date = 
ID = 10002 Date = 03/01/2017
ID =     Date = 02/01/2017
ID = 10001 Date = 
ID = 10001 Date = 
ID = 10001 Date = 01/01/2017

4 个答案:

答案 0 :(得分:0)

因此,如果我理解你的答案,你想按报告的ID排序,然后按日期排序。

改变这个:

    foreach (var report in reports.OrderByDescending(x => x.Date))
    {
        Console.WriteLine("ID = " + report.Id + " " + "Date = " + report.Date);
    }

到此:

    foreach (var report in reports.OrderByDescending(x => x.Id).ThenBy(x => x.Date))
    {
        Console.WriteLine("ID = " + report.Id + " " + "Date = " + report.Date);
    }

后者按其ID排序报告,然后按日期排序。

答案 1 :(得分:0)

如果我理解正确,您希望先按日期排序,如果日期为空,请使用ID进行排序。在这种情况下,您需要自定义报告比较器。

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Report> reports = new List<Report>();

            Report[] report1 =
            {
                new Report {Id = 10001, Date = null},
                new Report {Id = 10001, Date = null},
                new Report {Id = 10001, Date = Convert.ToDateTime("01/01/2017")}
            };


            Report[] report2 =
            {
                new Report {Id = 10002, Date = null},
                new Report {Id = 10002, Date = null},
                new Report {Id = 10002, Date = Convert.ToDateTime("03/01/2017")}
            };


            Report[] report3 =
            {
                new Report {Id = 10003, Date = null},
                new Report {Id = 10003, Date = null},
                new Report {Id = 10003, Date = Convert.ToDateTime("05/01/2017")}
            };


            Report[] report4 =
            {
                new Report {Id = 10004, Date = null},
                new Report {Id = 10004, Date = null},
                new Report {Id = 10004, Date = Convert.ToDateTime("07/01/2017")}
            };

            reports.AddRange(report1);
            reports.AddRange(report2);
            reports.AddRange(report3);
            reports.AddRange(report4);


            var report5 = new List<Report>()
            {
                new Report {Id = null, Date = Convert.ToDateTime("02/01/2017")},
                new Report {Id = null, Date = Convert.ToDateTime("04/01/2017")},
                new Report {Id = null, Date = Convert.ToDateTime("06/01/2017")},
            };

            reports.AddRange(report5);


            foreach (var report in reports.OrderByDescending(x => x, new ReportComparer()))
            {
                Console.WriteLine("ID = " + report.Id + " " + "Date = " + report.Date);
            }

            Console.ReadKey();
        }


         class ReportComparer: IComparer<Report>
        {
            public int Compare(Report x, Report y)
            {
                // write your ordering rules here
                if (x.Date.HasValue && y.Date.HasValue)
                {
                    return x.Date.Value.CompareTo(y.Date.Value);
                }
                return x.Id.Value.CompareTo(y.Id.Value);
            }
        }

        class Report
        {
            public int? Id { get; set; }
            public DateTime? Date { get; set; }
        }
    }
}

答案 2 :(得分:-1)

我建议不要使用linq。 我会创建自己的排序功能。 类似于冒泡排序simple bubble sort

您可以在哪里更改交换元素的条件。

答案 3 :(得分:-1)

您可以使用DateTime.MaxValue为您指定空日期,然后订购您的列表并使用DateTime.MaxValue重新分配null

  var reportlist = reports.OrderBy(n => n.Date = n.Date == null ? n.Date = DateTime.MaxValue : n.Date).Select(n=>n = new Report() {Date= n.Date == DateTime.MaxValue ? n.Date = null : n.Date, Id=n.Id }).ToList();


 foreach (var report in reportlist)
            {
                Console.WriteLine("ID = " + report.Id + " " + "Date = " + report.Date);
            }