C#日期时间数组

7

我有两个数组,array1包含了从上午8点到下午2点每分钟的日期时间数据,而array2则包含了同一天上午8点到下午1点每小时的日期时间数据。

我想输出两个数组中具有相同datetime.hour的索引号,并且它应该匹配array2的最后可用索引号,以便对于所有晚于array2的datetime数据,都可以匹配上。

例如,如果我有两个如下的datetime数组:

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),
        };

应该给我输出:

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

这是我尝试的:

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

但是在下午1点后,它不会输出索引号。

6
不错的初学者练习。你尝试了什么?或者你认为我们是一个“免费写代码”的服务吗?通常,我们希望人们基于代码有一个编程问题。而不是让他们把作业扔给我们,以便他们永远不学习编程。 - TomTom
你尝试过什么吗?使用循环可能很简单但有些低效 - 尝试一下,看看是否能想出更有效的方法。 - D Stanley
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Jon Skeet
2
我已经添加了我的代码 - J.Lin
你的两个列表长度不一样,朋友。所以你需要第一个循环,然后在它里面,你需要循环另一个列表。这样,对于循环1中的每个条目,你将把它与内部循环2中的所有条目进行比较。在内部循环中,你进行比较,如果它们匹配,则将它们添加到列表中。 - Andrew Truckle
3个回答

2
你的两个列表长度不同。在你的while语句中,你试图同时迭代两个不同长度的列表。
如果我正确理解你的要求,你应该使用内部循环来完成类似以下的操作:
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];
    }       

0
这是一个使用Array.FindIndexforeach的相当基本的方法:

编辑:更新了此答案以处理“匹配数组1中所有晚于array2的日期时间数据的最后可用索引号码”的问题。

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

}

这段代码简单地查看了dateTimes1dateTimes2中的每个值,并返回它找到的第一个匹配项(与您的循环非常相似)。

为了确定dt1index,我们遍历dateTimes1并返回第一个匹配项,其中a => a == dt(a只是谓词,表示在dateTimes1中的“当前”值 - 就像在常规循环中的i = 0,1,2等一样)。

同样,为了确定dt2index,我们寻找第一个匹配项,其中x => x.Hour == dt.Hour - 即,“当前”dt的小时字段与dateTimes2中的小时字段匹配。

在两种情况下,都返回第一个匹配项 - 如果找不到匹配项,则返回-1

当我们要写入控制台时,我们会检查currentHour是否大于dateTimes2中的最后一个小时,如果是,则只需写入dateTimes1的当前索引和dateTimes2的最后一个索引。否则,我们将写入dateTimes1的当前索引以及在dateTimes2上匹配小时的索引。


0
使用 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);
}

上述的Linq语句的作用:

  • 第一个Select使用了该方法的重载,同时传递了项目的索引。这只是允许该信息进行级联。它使用了一个匿名对象,其中索引和集合项分别是indexvalue属性。

  • Where子句查询这些匿名对象的集合,并将它们的valuedateTime1[i]进行比较。它获取那个value小于dateTime1[i]但不超过1小时的值,或者如果它是整个集合中的最大value

  • 第二个Select仅获取通过Where筛选的项目的索引。

  • FirstOrDefault返回的就是这个(即选择的项目的索引,如果没有选择任何项目,则为0)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接