-1

I am having 2 reports and combining them into a list. some of the item has null values.when i do sorting, it moves null values at the last.

Here is the sample program

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; }
    }
}

Sorting should be made based on the date and should not skip/move the null values of report list. Output should be as follows.

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
  • You should read the [Linq To Objects documentation](https://learn.microsoft.com/en-us/dotnet/articles/csharp/programming-guide/concepts/linq/linq-to-objects). – Jeroen Heier May 24 '17 at 04:00
  • You need to clarify how you want the output sorted. If sorted by ID, the IDs, that are null, will be grouped together. If sorted by their date, the null dates will be grouped together. When do you want a null date to be grouped with a certain set of ID's, and by what information in the ``Report`` objects can that be achieved? – J.N. May 24 '17 at 04:24

4 Answers4

0

So, if I understood your answer correctly, you want to order by the ID's of the reports, and then the dates.

Change this:

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

to this:

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

The latter sorts the reports by their ID, then by their date.

J.N.
  • 537
  • 2
  • 10
  • He can't be sorting by ID's there are null valued id's spread throughout the resultset – Daniel May 24 '17 at 04:11
  • Sorting by multiple fields is more like grouping and then sorting within those groups. He seems to be looking for a conditional sort which is why I suggested he writes his own. – russelrillema May 24 '17 at 04:17
  • True, his null ID's will be grouped together with my code. I have asked for clarification. – J.N. May 24 '17 at 04:25
  • Alright, let me try to get answers in another way - **why** should the entry ``ID = Date = 06/01/2017`` come before the entry ``ID = 10003 Date = ``? – J.N. May 24 '17 at 04:30
  • both are different reports that i am getting from different agents. final report should be made as i mentioned in the output – arjunan May 24 '17 at 04:38
  • @arjunan - The question remains unanswered. On what basis will you determine that the entry ``ID = Date = 06/01/2017`` should come before the entry ``ID = 10003 Date = ?``. Is it because that any entry with a null ID should come before entries with an ID? You will need to explain how the ordering of these two elements are determined before anyone can help you any further. – J.N. May 24 '17 at 04:42
0

If I understood correctly, you want to order by Date first, and if Date is null, use ID for ordering. In this case, you need custom Report comparer.

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; }
        }
    }
}
Orifjon
  • 915
  • 8
  • 25
  • I could not figure out your rules to sort your reports. Please clarify your rules and we can update comparer accordingly. – Orifjon May 24 '17 at 04:48
  • some id values are null. if i try about method, it would throw null ref exception. – arjunan May 24 '17 at 04:54
  • @arjunan I did not check for nulls in example. You can use your logic how to compare two Reports including nulls. – Orifjon May 24 '17 at 06:52
-1

I would recommend not using linq for this. I would create your own sort function. Something like a bubble sort simple bubble sort

Where you can change the condition for swapping the elements.

russelrillema
  • 452
  • 7
  • 14
  • Any reason for the down vote? I thought it was a valid suggestion. I think if you down vote you should specify why so that we can all improve? – russelrillema Oct 04 '19 at 04:02
-1

You can do as assign you null Date with DateTime.MaxValue then order your list and reassign DateTime.MaxValue with 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);
            }
Azar Shaikh
  • 445
  • 9
  • 26
  • That would simply put the entries with a null ``Date`` last, which is not what he wants (even though it is a bit unclear what he wants). – J.N. May 24 '17 at 04:37
  • No. I am not getting the output in mentioned in the query – arjunan May 24 '17 at 04:39