简体   繁体   中英

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.

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

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 .

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM