Search code examples
c#sortingdate-sorting

C# Sort Object[] Array within ArrayList?


I am not sure how to go about sorting the ArrayList which contains an object Array which has a DateTime object and a String object. I am ultimately trying to sort the ArrayList based on the first object (DateTime) of the array within the ArrayList.

I've tried to search around for sorting but articles didn't seem to go into the level of detail or this particular use-case the application is hitting. I'm not sure if this is the best way to deal with the data either but any help suggestion will certainly be appreciative.

The goal is to read mutliple XML files and combine all the Lap data out of the all the XML files and sort them from oldest to most recent then to create a new XML file with the combined sorted information in it.

ArrayList LapsArrayList = new ArrayList();

ListBox.SelectedObjectCollection SelectedItems = lstSelectedFiles.SelectedItems;

foreach (string Selected in SelectedItems)
{
    Object[] LapArray = new Object[2];

    XmlDocument xDoc = new XmlDocument();
    xDoc.Load(Path + @"\" + Selected);

    XmlNodeList Laps = xDoc.GetElementsByTagName("Lap");

    foreach (XmlElement Lap in Laps)
    {
        LapArray[0] = DateTime.Parse(Lap.Attributes[0].Value);
        LapArray[1] = Lap.InnerXml.ToString();
        LapsArrayList.Add(LapArray);
    }
}

XML Data Example

<Lap StartTime="2013-06-17T12:27:21Z"><TotalTimeSeconds>12705.21</TotalTimeSeconds><DistanceMeters>91735.562500</DistanceMeters><MaximumSpeed>10.839000</MaximumSpeed><Calories>3135</Calories><AverageHeartRateBpm><Value>151</Value>.....</Lap>

Solution

  • This are my recommendations:

    1. Use a class for the items you want to sort, I suggest a Tuple<T1, T2>.
    2. Use a List<T> because it is a typed list so you avoid casts and it is more convenient in general.
    3. We are going to use Linq to sort the array just for easy writting.

    I list the code below:

    //I dunno what does this has to do, but I'll leave it here
    ListBox.SelectedObjectCollection SelectedItems = lstSelectedFiles.SelectedItems;
    
    //We are going to use a List<T> instead of ArrayList
    //also we are going to use Tuple<DateTime, String> for the items
    var LapsList = new List<Tuple<DateTime, String>>();
    
    foreach (string Selected in SelectedItems)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(Path + @"\" + Selected);
        XmlNodeList Laps = xDoc.GetElementsByTagName("Lap");
        foreach (XmlElement Lap in Laps)
        {
            var dateTime = DateTime.Parse(Lap.Attributes[0].Value);
            var str = Lap.InnerXml.ToString();
            //Here we create the tuple and add it
            LapsList.Add(new Tuple<DateTime, String>(dateTime, str));
        }
    }
    
    //We are sorting with Linq
    LapsList = LapsList.OrderBy(lap => lap.Item1).ToList();
    

    If you can't use tuples, declare you own class for the item. For example

    class Lap
    {
        private DateTime _dateTime;
        private String _string;
    
        public Lap (DateTime dateTimeValue, String stringValue)
        {
            _dateTime = dateTimeValue;
            _string = stringValue;
        }
    
        public DateTime DateTimeValue
        {
            get
            {
                return _dateTime;
            }
            set
            {
                _dateTime = value;
            }
        }
    
        public String StringValue
        {
            get
            {
                return _string;
            }
            set
            {
                _string = value;
            }
        }
    }
    

    With this class you can do a easy migration of the code as follows:

    //I dunno what does this has to do, but I'll leave it here
    ListBox.SelectedObjectCollection SelectedItems = lstSelectedFiles.SelectedItems;
    
    //We are going to use a List<T> instead of ArrayList
    //also we are going to use the Laps class for the items
    var LapsList = new List<Lap>();
    
    foreach (string Selected in SelectedItems)
    {
        XmlDocument xDoc = new XmlDocument();
        xDoc.Load(Path + @"\" + Selected);
        XmlNodeList Laps = xDoc.GetElementsByTagName("Lap");
        foreach (XmlElement Lap in Laps)
        {
            var dateTime = DateTime.Parse(Lap.Attributes[0].Value);
            var str = Lap.InnerXml.ToString();
            //Here we create the Lap object and add it
            LapsList.Add(new Lap(dateTime, str));
        }
    }
    
    //We are sorting with Linq
    LapsList = LapsList.OrderBy(lap => lap.DateTimeValue).ToList();
    

    If you can't use Linq, here is a non Linq alternative:

    LapsList.Sort
    (
        delegate(Tuple<DateTime, String> p1, Tuple<DateTime, String> p2)
        {
            return p1.Item1.CompareTo(p2.Item1);
        }
    );
    

    Or for the case of using the Lap class:

    LapsList.Sort
    (
        delegate(Lap p1, Lap p2)
        {
            return p1.DateTimeValue.CompareTo(p2.DateTimeValue);
        }
    );