J.Lin
J.Lin

Reputation: 71

C# datetime array

I have two arrays, array1 has datetime data count by minute from 8am to 2pm and array2 has datetime data count by hour from same date 8am to 1pm.

I want to output the index number of two array that has same datetime.hour. and it should matchup the last available index number of array2 for all of the datetime data from array1 that later than array2.

for example if I have two datetime array like this:

DateTime[] dateTimes1 = new DateTime[]
        {

            new DateTime(2010, 10, 1, 8, 15, 0),
            new DateTime(2010, 10, 1, 8, 30, 1),
            new DateTime(2010, 10, 1, 8, 45, 2),
            new DateTime(2010, 10, 1, 9, 15, 3),
            new DateTime(2010, 10, 1, 9, 30, 4),
            new DateTime(2010, 10, 1, 9, 45, 5),
            new DateTime(2010, 10, 1, 10, 15, 6),
            new DateTime(2010, 10, 1, 10, 30, 7),
            new DateTime(2010, 10, 1, 10, 45, 8),
            new DateTime(2010, 10, 1, 11, 15, 9),
            new DateTime(2010, 10, 1, 11, 30, 10),
            new DateTime(2010, 10, 1, 11, 45, 11),
            new DateTime(2010, 10, 1, 12, 15, 12),
            new DateTime(2010, 10, 1, 12, 30, 13),
            new DateTime(2010, 10, 1, 12, 45, 14),
            new DateTime(2010, 10, 1, 13, 15, 15),
            new DateTime(2010, 10, 1, 13, 30, 16),
            new DateTime(2010, 10, 1, 13, 45, 17),
            new DateTime(2010, 10, 1, 14, 15, 18),
            new DateTime(2010, 10, 1, 14, 30, 19),
            new DateTime(2010, 10, 1, 14, 45, 20),
        };

        DateTime[] dateTimes2 = new DateTime[]
        {
            new DateTime(2010, 10, 1, 8, 0, 0),
            new DateTime(2010, 10, 1, 9, 0, 1),
            new DateTime(2010, 10, 1, 10, 0, 2),
            new DateTime(2010, 10, 1, 11, 0, 3),
            new DateTime(2010, 10, 1, 12, 0, 4),
            new DateTime(2010, 10, 1, 13, 0, 5),
        };

it should gives me the output:

0, 0
1, 0
2, 0
3, 1
4, 1
5, 1
6, 2
7, 2
8, 2
9, 3
10, 3
11, 3
12, 4
13, 4
14, 4
15, 5
16, 5
17, 5
18, 5
19, 5
20, 5

This is what I have tried:

            int i = 0;
            int j = 0;
            while (i < dateTimes1.Length && j < dateTimes2.Length)
            {     
                if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
                {
                    list.Add(i);
                    list2.Add(j);
                    i++;
                }
                else if (dateTimes1[i] < dateTimes2[j])
                {
                    i++;
                }
                else if (dateTimes1[i] > dateTimes2[j])
                {
                    j++;
                }
            }
            for (int k = 0; k < list.Count; k++)
            {
                Console.WriteLine(list[k] + " , " + list2[k];
            }

but it won't output the index number after 1pm.

Upvotes: 7

Views: 5902

Answers (3)

Frank Fajardo
Frank Fajardo

Reputation: 7369

Using Linq:

var hour = new TimeSpan(1, 0, 0);
var dt2MaxValue = dateTimes2.Max();
for (int i = 0; i < dateTimes1.Length; i++)
{
    var output = string.Format("{0}, {1}",
        i,
        dateTimes2
           .Select((o, index) => new { index = index, value = o })
           .Where(dt2 => (dateTimes1[i] - dt2.value) < hour 
                           || dt2.value == dt2MaxValue)
           .Select(dt2 => dt2.index)
           .FirstOrDefault());
    Console.WriteLine(output);
}

What the above Linq statement does:

  • The first Select uses that method's overload which also passes the index of the item. This simply allows that info to cascade through. It uses an anonymous object with both index and the collection item being the index and value properties, respectively.

  • The Where clause queries the collection of these anonymous objects and compares their value with dateTime1[i]. It gets the one where value is less than dateTime1[i] but not by more than 1 hour, OR if it is the maximum value in the whole collection.

  • The second Select simply gets the indexes of the items that Where filtered through.

  • And FirstOrDefault returns just that (ie, the first or default, which is the index of the item selected or 0 if no item was selected).

Upvotes: 0

levelonehuman
levelonehuman

Reputation: 1505

Here's a pretty basic method using Array.FindIndex and foreach:

EDIT: Updated this answer to handle the "matchup the last available index number of array2 for all of the datetime data from array1 that later than array2." issue.

foreach (DateTime dt in dateTimes1)
{   
    int currentHour = dt.Hour;
    int lastHour = dateTimes2[dateTimes2.GetUpperBound(0)].Hour; //GetUpperBound(0) is the last index

    int dt1index = Array.FindIndex(dateTimes1, a => a == dt); //get the index of the current item in dateTimes1
    int dt2index = Array.FindIndex(dateTimes2, x => x.Hour == currentHour); //get the index of the item in dateTimes2 matching dateTimes1 hour field        

    if (currentHour > lastHour)
    {
        Console.WriteLine("{0}, {1}", dt1index, dateTimes2.GetUpperBound(0));
    }
    else
    {
        Console.WriteLine("{0}, {1}", dt1index, dt2index);
    }             

}

This simply looks at each of the values in dateTimes1 and dateTimes2 and returns the first match it finds (very similar to your loop).

To determine dt1index, we look through dateTimes1 and return the first match where a => a == dt (a is just the predicate, representing the "current" value in dateTimes1 - think of i = 0,1,2,etc in a regular loop ).

Similarly, to determine dt2index, we look for the first match on x => x.Hour == dt.Hour -- that is, where the "current" dt's hour field matches the hour field in dateTimes2.

In both cases, the first match is returned - if no matches are found, -1 is returned.

When we go to write to the console, we check if currentHour is greater than the last hour in dateTimes2 if so, we just write the current index of dateTimes1 and the last index of dateTimes2. Otherwise, we write the current index of dateTimes1 and the index where the hour matches on dateTimes2.

Upvotes: 0

Andrew Truckle
Andrew Truckle

Reputation: 19207

Your two lists are not the same length. In your while statement you are trying to iterate two different length lists at the same time.

If I understand your requirements properly you should be doing something like this by using an inner loop:

DateTime[] dateTimes1 = new DateTime[]
    {

        new DateTime(2010, 10, 1, 8, 15, 0),
        new DateTime(2010, 10, 1, 8, 30, 1),
        new DateTime(2010, 10, 1, 8, 45, 2),
        new DateTime(2010, 10, 1, 9, 15, 3),
        new DateTime(2010, 10, 1, 9, 30, 4),
        new DateTime(2010, 10, 1, 9, 45, 5),
        new DateTime(2010, 10, 1, 10, 15, 6),
        new DateTime(2010, 10, 1, 10, 30, 7),
        new DateTime(2010, 10, 1, 10, 45, 8),
        new DateTime(2010, 10, 1, 11, 15, 9),
        new DateTime(2010, 10, 1, 11, 30, 10),
        new DateTime(2010, 10, 1, 11, 45, 11),
        new DateTime(2010, 10, 1, 12, 15, 12),
        new DateTime(2010, 10, 1, 12, 30, 13),
        new DateTime(2010, 10, 1, 12, 45, 14),
        new DateTime(2010, 10, 1, 13, 15, 15),
        new DateTime(2010, 10, 1, 13, 30, 16),
        new DateTime(2010, 10, 1, 13, 45, 17),
        new DateTime(2010, 10, 1, 14, 15, 18),
        new DateTime(2010, 10, 1, 14, 30, 19),
        new DateTime(2010, 10, 1, 14, 45, 20),
    };

    DateTime[] dateTimes2 = new DateTime[]
    {
        new DateTime(2010, 10, 1, 8, 0, 0),
        new DateTime(2010, 10, 1, 9, 0, 1),
        new DateTime(2010, 10, 1, 10, 0, 2),
        new DateTime(2010, 10, 1, 11, 0, 3),
        new DateTime(2010, 10, 1, 12, 0, 4),
        new DateTime(2010, 10, 1, 13, 0, 5),
    };

    int i = 0;
    while (i < dateTimes1.Length)
    {
        int j = 0;
        while (j < dateTimes2.Length))
        {
            if (dateTimes1[i].Date == dateTimes2[j].Date && dateTimes1[i].Hour == dateTimes2[j].Hour)
            {
                list.Add(i);
                list2.Add(j);
                i++;
            }
            else if (dateTimes1[i] < dateTimes2[j])
            {
                i++;
            }
            else if (dateTimes1[i] > dateTimes2[j])
            {
                j++;
            }
        }
    }
    for (int k = 0; k < list.Count; k++)
    {
        Console.WriteLine(list[k] + " , " + list2[k];
    }       

Upvotes: 2

Related Questions