0

I have a problem.

I have an ArrayList of objects. Each object contains a DateTime data field.

I need to sort this ArrayList by this DateTime data field.

This is my current code and it does not work:

        for (int i = 0;i<EventHolder.Count;i++)
        {
            Event obj = (Event) EventHolder[i];
            try
            {
                obj2=(Event)EventHolder[i+1];
            }
            catch
            {
                break;
            }
            DateTime date1 = DateTime.ParseExact(obj.Date_And_Time,"dd/MM/yyyy HH:mm",region);
            DateTime date2 = DateTime.ParseExact(obj2.Date_And_Time, "dd/MM/yyyy HH:mm", region);
            if (DateTime.Compare(date1,date2)>0)
            {
                Event tempobj=obj2;
                EventHolder[i+1]=obj;
                EventHolder[i]=tempobj;
            }
        }
        foreach (Event i in EventHolder)
        {
            Console.WriteLine(i.Date_And_Time);
        }
        Console.ReadLine();

I use these 3 dates to test if it works:

23/11/2011 12:15

28/06/2010 04:05

02/09/1992 03:54

The output is always:

28/06/2010 04:05

02/09/1992 03:54

23/11/2011 12:15

I tried using just > and < operators for comparing and got same results. I also tried using different commands to convert the strings to DateTime objects, like Convert.ToDateTime, DateTime.Parse. Tried entering without HH:mm (adjusted the code accordingly) and still had the same output. I tried not using IFormatProvider (set it to null) and got nowhere again.

By chance, I found this thread:

How to sort ArrayList of DateTime objects in descending order?

I extracted all the dates from the objects and put them into this DateTime list. Used List.Sort() and it produced correct output. But then I got stuck at how to use this sorted list to sort my EventHolder ArrayList. I've been banging on this wall for a while, and produced no result.

I am very new to programming, so I hardly know any good way of doing what I'm doing. And it doesn't even work. Can anybody explain to me where I'm going wrong?

Community
  • 1
  • 1
eltaro
  • 121
  • 1
  • 10
  • Do you have to stick to the old and ugly ArrayList? If you used generic collections and LINQ, this whole task could be done in 1 line of code. – Jacek Gorgoń Mar 01 '12 at 15:34
  • Can use List instead, doesn't have to be an arraylist. – eltaro Mar 01 '12 at 15:51
  • I'd recommend not to use LINQ for something like this. You may get only a single line of code but it'll be significantly slower than just using `ArrayList.Sort()` or `List.Sort()`. – xxbbcc Mar 01 '12 at 16:35
  • I'm right now trying to do List.Sort() using Miky's example with Lambda expression, but it does not work =_= and I don't know why. It just gives this: Cannot Convert lambda expression to type: 'System.Collections.Generic.IComparer because it's not a delegate type. – eltaro Mar 01 '12 at 16:47
  • xxbbcc: http://stackoverflow.com/questions/1832684/c-sharp-sort-and-orderby-comparison says otherwise. – Jacek Gorgoń Mar 02 '12 at 08:31

4 Answers4

0

Use this overload of ArrayList.Sort() - you'll get a callback for every comparison with your objects and you can then easily compare two dates inside your objects.

public class MyDateComparer : IComparer
{
    int IComparer.Compare ( Object x, Object y )
    {
        // Cast x and y to your object type and then compare the dates. Return
        // -1, 0 or 1 depending on your comparison
        return ( ... );
    }
}

...

myList.Sort ( 0, myList.Length, new MyDateComparer () );
xxbbcc
  • 16,930
  • 5
  • 50
  • 83
0

That's a wrong approach imo, a better way to do this is to use a Custom comparer.

   public class SortByDateTime: IComparer  {
      // Calls CaseInsensitiveComparer.Compare with the parameters reversed.
      int IComparer.Compare( Object x, Object y )  {
          // Compare objects according to the date
          }
      }

   ...
   // Sort the arraylist using the custom comparer
   IComparer myComparer = new SortByDateTime();
   ArrayList mList = new ArrayList();
   mList.Sort(myComparer);
Shai
  • 25,159
  • 9
  • 44
  • 67
  • I don't think ArrayList is a generic type. You may want to correct your example. – xxbbcc Mar 01 '12 at 15:29
  • thank you for your fast replies. I am right now trying to understand this piece of code and adapt it to my program. – eltaro Mar 01 '12 at 15:34
0

What you're trying to do there is implement a sorting algorithm but unfortunately yours is not a correct one. It almost looks like Bubble Sort which is a pretty slow algorithm to begin with but it's not quite correct.

A much better way to accomplish what you're trying to do is to use the Sort method or ArrayList or of the generic List<> classes. Those sort methods allow you to provide an IComparer implementation (or a comparison delegate in the case of the generic List) to specify the sort criteria and internally they use a correct and efficient sort algorithm.

If you use the generic List<> you could just pass in a lambda expression and have it dictate the sorting criteria based on the date field, like so:

// Assuming EventHolder is a List<Event>
EventHolder.Sort((d1, d2) => DateTime.ParseExact(d1.Date_And_Time,"dd/MM/yyyy HH:mm",region).CompareTo(DateTime.ParseExact(d2.Date_And_Time,"dd/MM/yyyy HH:mm",region)));
Mike Dinescu
  • 54,171
  • 16
  • 118
  • 151
  • whats a lambda expression? I tried this code, it gives out an error, Cannot Convert lambda expression to type: 'System.Collections.Generic.IComparer because it's not a delegate type. – eltaro Mar 01 '12 at 15:44
  • This comment box is not enough space to explain what a lambda expression is, so I'm just going to try to give you an idea as it applies in your case: Think of it as an anonymous function, declared inline, that is interpreted by the compiler as a delegate. In my example the lambda expression is (d1,d2) => ... Which is like declaring a function that takes two parameters d1 and d2 of type Event in that case, and then returns (=>) the result of a computation using the two parameters. For details, see he MSDN page on lambda expressions here: http://msdn.microsoft.com/en-us/library/3da4abas.aspx – Mike Dinescu Mar 01 '12 at 15:49
  • I've converted EventHolder to List, and added your code. It gives me an error still. Adding using System.Linq; did not help either. – eltaro Mar 01 '12 at 16:32
  • Thanks, I've fixed it. Visual Studio was unhappy for no reason. I've transfered the code to another project and it worked. – eltaro Mar 01 '12 at 17:04
0

If you don't really need ArrayList and have .NET 3.5, try the following instead:

List<Event> eventHolder = ... // Just to make certain it's a List<Event>
eventHolder = eventHolder
    .OrderBy(e => DateTime.ParseExact(e.Date_And_Time,"dd/MM/yyyy HH:mm",region)
    .ToList();
Jacek Gorgoń
  • 3,206
  • 1
  • 26
  • 43