none
Order of data has changed after sorting with date values in data. RRS feed

  • Question

  • Hi,

    I have a custom class with some fields (Subject and StartTime) and custom comparer for sorting the time values and stored data in ArrayList collection.

    Sample Data in collection:

    Subject = App1 and StartTime = 25/11/2019

    Subject = App1 and StartTime = 26/11/2019

    Subject = App1 and StartTime = 27/11/2019

    Subject = App1 and StartTime = 28/11/2019

    Subject = App1 and StartTime = 29/11/2019                           

    Subject = App1 and StartTime = 30/11/2019

    Subject = App1 and StartTime = 01/12/2019

    Subject = App2 and StartTime = 25/11/2019

    Subject = App2 and StartTime = 26/11/2019

    Subject = App2 and StartTime = 27/11/2019

    Subject = App2 and StartTime = 28/11/2019

    Subject = App2 and StartTime = 29/11/2019

    Subject = App2 and StartTime = 30/11/2019

    Subject = App2 and StartTime = 01/12/2019

    Subject = App3 and StartTime = 25/11/2019

    Subject = App3 and StartTime = 26/11/2019

    Subject = App3 and StartTime = 27/11/2019

    Subject = App3 and StartTime = 28/11/2019

    Subject = App3 and StartTime = 29/11/2019

    Subject = App3 and StartTime = 30/11/2019

    Subject = App3 and StartTime = 01/12/2019

    Problem:

    FYI : Date values in collection are from 25/11/2019 to 01/12/2019 (including Saturday and Sunday).                                                                                             

    After sorting the date values, times are sorted properly but objects or records order is changed.

    Expected result:

    Subject = App1 and StartTime = 25/11/2019

    Subject = App2 and StartTime = 25/11/2019

    Subject = App3 and StartTime = 25/11/2019

    Subject = App1 and StartTime = 26/11/2019

    Subject = App2 and StartTime = 26/11/2019

    Subject = App3 and StartTime = 26/11/2019

    Observed result:

    Subject = App1 and StartTime = 25/11/2019

    Subject = App3 and StartTime = 25/11/2019

    Subject = App2 and StartTime = 25/11/2019

    Subject = App1 and StartTime = 26/11/2019

    Subject = App3 and StartTime = 26/11/2019

    Subject = App2 and StartTime = 26/11/2019

    //

    //

    Subject = App3 and StartTime = 28/11/2019

    Subject = App2 and StartTime = 28/11/2019

    Subject = App1 and StartTime = 28/11/2019

    Note: This problem occurs only when collection has Saturday and Sunday values (30/11/2019 and 01/12/2019).

    If don’t have that 2 dates in collection, the records are in correct order as expected result after sorting.

    Here I have attached sample demo & screenshots for your reference.

    Please guide me to have sorted objects in correct order as expected result (with Sat and Sun dates) and let me know if I did anything wrong.

    Code:

    //main method
    ArrayList collection = new ArrayList();
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 7; j++)
                    {
                        TestDate t = new TestDate() { Subject = "App" + (i + 1).ToString() };
                        DateTime date = new DateTime(2019, 11, 25);
                        t.StartTime = date.AddDays(j);
                        collection.Add(t);
                    }
                }
                StartDateComparer comp = new StartDateComparer();
                collection.Sort(comp);
    
    
    //Custom Comparer
    public class StartDateComparer : IComparer
        {
            #region IComparer Members      
            public int Compare(object x, object y)
            {
                TestDate xItem = x as TestDate;
                TestDate yItem = y as TestDate;
                if (xItem == null && yItem == null)
                {
                    return 0;
                }
                else if (xItem == null)
                {
                    return -1;
                }
                else if (yItem == null)
                {
                    return 1;
                }
                else
                {
                    int c = xItem.StartTime.CompareTo(yItem.StartTime);
                    if (c == 0)
                        c = xItem.StartTime.Date.CompareTo(yItem.StartTime.Date);
                    return c;
                }
            }
            #endregion
        }
    
    
    
    

    Thanks,

    Wednesday, December 18, 2019 8:38 AM

Answers

  • Actually i do not want to sort Subject. i'm having 3 span appointments (continuous dates) named as "A", "B", "C" with dates (25/11/2019 to 01/12/2019).

    3 Span appointments are like below,

    "A" 25/11/2019 to 01/12/2019

    "B" 25/11/2019 to 01/12/2019

    "C" 25/11/2019 to 01/12/2019

    I need to show  them in order as user added.

    i can show them in grid cells (cells are: Nov 25 , 26, 27,... Dec 01). I want to show ("A" - 25/11/2019 , "B"-25/11/2019, "C"-25/11/2019) in a cell which text is "Nov 25", and same like this , have to show remaining data in respective cells ("26,"27",..."01/12").

    So that i have split and stored the each date in collection and sort them by date to set the proper order like below,

    A - 25/11/2019

    B - 25/11/2019

    C - 25/11/2019

    But the orders are changed in collection after sorting. As i said earlier, this problem occurs when having 30/11/2019 and 01/12/2019 dates in each appointment.

    So that i prepared the simple demo for understanding, please check the sample and see the output by modifying for loop iteration limit 5 and 7.

    please let me know if you need any details.


    Accordingly you want to sort by date and then by id. The id is an incrementing value which is automatically set when you enter a new data entry into the collection.

    If you don't have this id (because you don't use a database or something), then you must add it to the data class on your own.

    A normal sort algorithm does not know the order how data was added into a collection. You must give each data an id that is incrementing when the data is entered into the collection.

    Regards, Guido

    Edit: Something like:

    // 1. Add an int id to your class TestDate
    
    // 2. main method
    ArrayList collection = new ArrayList();
                int auto_id = 0;
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 7; j++)
                    {
                        TestDate t = new TestDate() { Subject = "App" + (i + 1).ToString() };
                        DateTime date = new DateTime(2019, 11, 25);
                        t.StartTime = date.AddDays(j);
                        t.id = ++auto_id;
                        collection.Add(t);
                    }
                }
                StartDateComparer comp = new StartDateComparer();
                collection.Sort(comp);
    
    
    //Custom Comparer
    public class StartDateComparer : IComparer
        {
            #region IComparer Members      
            public int Compare(object x, object y)
            {
                TestDate xItem = x as TestDate;
                TestDate yItem = y as TestDate;
                if (xItem == null && yItem == null)
                {
                    return 0;
                }
                else if (xItem == null)
                {
                    return -1;
                }
                else if (yItem == null)
                {
                    return 1;
                }
                else
                {
                    int c = xItem.StartTime.CompareTo(yItem.StartTime);
                    if (c == 0)
                    {
                         if (xItem.id < yItem.id) return -1;
                         if (xItem.id > yItem.id) return 1;
                    }
                    return c;
                }
            }
            #endregion
        }
    
    (I don't know the exact C# Syntax, so correct my code)


    • Edited by Guido Franzke Thursday, December 19, 2019 7:12 AM added code
    • Marked as answer by Piruthiv Friday, December 20, 2019 6:12 AM
    Thursday, December 19, 2019 7:06 AM

All replies

  • Hi Piruthiv,

    Thank you for posting here.

    For your question, you sort the list based on two properties of your class.

    However, you compared StartTime twice without comparing Subject. 

    Try the following code.

    int c = xItem.StartTime.Date.CompareTo(yItem.StartTime.Date);
    if (c == 0)
       c = xItem.Subject.CompareTo(yItem.Subject);

    Hope this could be helpful.

    Best Regards, 

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Wednesday, December 18, 2019 9:29 AM
  • Hi Timon,

    Thanks for your update.

    If i used/replaces subject name as starts with "B" for "App2", the order will be like "App1","App3","B".

    So sorting the subject is not works for me.

    As i said earlier, if data does not contain "Saturday (30/11) and Sunday (01/12)", the orders not changed. This problem occurs only when including Saturday and Sunday.

    Can you please look into this and provide me any ideas?

    For more details:

    My project is like Schedule control (custom control) and users can add 3 span appointments (25/11 to 01/12) which has Saturday and Sunday. When i'm trying to display them in UI, those orders are changed. So that i analyzed the problem, and find that orders are changed when sorting the appointment collection. so that i have prepared the simple demo for your reference.

    Wednesday, December 18, 2019 1:08 PM
  • If i used/replaces subject name as starts with "B" for "App2", the order will be like "App1","App3","B".

    So sorting the subject is not works for me.

    As i said earlier, if data does not contain "Saturday (30/11) and Sunday (01/12)", the orders not changed. This problem occurs only when including Saturday and Sunday.

    Can you please look into this and provide me any ideas?

    For more details:

    My project is like Schedule control (custom control) and users can add 3 span appointments (25/11 to 01/12) which has Saturday and Sunday. When i'm trying to display them in UI, those orders are changed. So that i analyzed the problem, and find that orders are changed when sorting the appointment collection. so that i have prepared the simple demo for your reference.

    Well, look at your "expected" results in your question. Your sort order was date and then subject. So Timon's answer was correct.
    And when you add "B", then the sort order is correct too, because "B">"A..". So how do you want to sort? You still need the second sort order, but you should think about how you want to sort. Maybe you want the second sort order to be the id? Please explain precisly how you really want to sort, so that we can help you.
    Wednesday, December 18, 2019 1:30 PM
  • Actually i do not want to sort Subject. i'm having 3 span appointments (continuous dates) named as "A", "B", "C" with dates (25/11/2019 to 01/12/2019).

    3 Span appointments are like below,

    "A" 25/11/2019 to 01/12/2019

    "B" 25/11/2019 to 01/12/2019

    "C" 25/11/2019 to 01/12/2019

    I need to show  them in order as user added.

    i can show them in grid cells (cells are: Nov 25 , 26, 27,... Dec 01). I want to show ("A" - 25/11/2019 , "B"-25/11/2019, "C"-25/11/2019) in a cell which text is "Nov 25", and same like this , have to show remaining data in respective cells ("26,"27",..."01/12").

    So that i have split and stored the each date in collection and sort them by date to set the proper order like below,

    A - 25/11/2019

    B - 25/11/2019

    C - 25/11/2019

    But the orders are changed in collection after sorting. As i said earlier, this problem occurs when having 30/11/2019 and 01/12/2019 dates in each appointment.

    So that i prepared the simple demo for understanding, please check the sample and see the output by modifying for loop iteration limit 5 and 7.

    please let me know if you need any details.


    • Edited by Piruthiv Thursday, December 19, 2019 6:52 AM
    Thursday, December 19, 2019 6:50 AM
  • Actually i do not want to sort Subject. i'm having 3 span appointments (continuous dates) named as "A", "B", "C" with dates (25/11/2019 to 01/12/2019).

    3 Span appointments are like below,

    "A" 25/11/2019 to 01/12/2019

    "B" 25/11/2019 to 01/12/2019

    "C" 25/11/2019 to 01/12/2019

    I need to show  them in order as user added.

    i can show them in grid cells (cells are: Nov 25 , 26, 27,... Dec 01). I want to show ("A" - 25/11/2019 , "B"-25/11/2019, "C"-25/11/2019) in a cell which text is "Nov 25", and same like this , have to show remaining data in respective cells ("26,"27",..."01/12").

    So that i have split and stored the each date in collection and sort them by date to set the proper order like below,

    A - 25/11/2019

    B - 25/11/2019

    C - 25/11/2019

    But the orders are changed in collection after sorting. As i said earlier, this problem occurs when having 30/11/2019 and 01/12/2019 dates in each appointment.

    So that i prepared the simple demo for understanding, please check the sample and see the output by modifying for loop iteration limit 5 and 7.

    please let me know if you need any details.


    Accordingly you want to sort by date and then by id. The id is an incrementing value which is automatically set when you enter a new data entry into the collection.

    If you don't have this id (because you don't use a database or something), then you must add it to the data class on your own.

    A normal sort algorithm does not know the order how data was added into a collection. You must give each data an id that is incrementing when the data is entered into the collection.

    Regards, Guido

    Edit: Something like:

    // 1. Add an int id to your class TestDate
    
    // 2. main method
    ArrayList collection = new ArrayList();
                int auto_id = 0;
                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < 7; j++)
                    {
                        TestDate t = new TestDate() { Subject = "App" + (i + 1).ToString() };
                        DateTime date = new DateTime(2019, 11, 25);
                        t.StartTime = date.AddDays(j);
                        t.id = ++auto_id;
                        collection.Add(t);
                    }
                }
                StartDateComparer comp = new StartDateComparer();
                collection.Sort(comp);
    
    
    //Custom Comparer
    public class StartDateComparer : IComparer
        {
            #region IComparer Members      
            public int Compare(object x, object y)
            {
                TestDate xItem = x as TestDate;
                TestDate yItem = y as TestDate;
                if (xItem == null && yItem == null)
                {
                    return 0;
                }
                else if (xItem == null)
                {
                    return -1;
                }
                else if (yItem == null)
                {
                    return 1;
                }
                else
                {
                    int c = xItem.StartTime.CompareTo(yItem.StartTime);
                    if (c == 0)
                    {
                         if (xItem.id < yItem.id) return -1;
                         if (xItem.id > yItem.id) return 1;
                    }
                    return c;
                }
            }
            #endregion
        }
    
    (I don't know the exact C# Syntax, so correct my code)


    • Edited by Guido Franzke Thursday, December 19, 2019 7:12 AM added code
    • Marked as answer by Piruthiv Friday, December 20, 2019 6:12 AM
    Thursday, December 19, 2019 7:06 AM
  • Unfortunately, it seems that not all sorting functions perform “stable sort”, which preserves the order of elements having equal keys.

    According to https://social.msdn.microsoft.com/Forums/vstudio/en-US/f5ea4976-1c3d-4e10-90e7-c7a0491fc28a, try a different approach:

     

    List<TestDate> collection = new List<TestDate>( );

    . . .

    collection = collection.OrderBy( t => t, comp ).ToList( );

    . . .

    public class StartDateComparer : IComparer<TestDate>

    {

       public int Compare( TestDate x, TestDate y )

       {

          if( object.ReferenceEquals( x, y ) ) return 0;

          if( x == null ) return -1;

          if( y == null ) return +1;

          return x.StartTime.CompareTo( y.StartTime );

       }

    }



    • Edited by Viorel_MVP Thursday, December 19, 2019 6:28 PM
    Thursday, December 19, 2019 6:20 PM
  • @Guido Thanks for your suggestion. I can use this in my code.
    Friday, December 20, 2019 6:12 AM