虽然循环困难

时间:2011-08-10 05:16:51

标签: c#

我正在尝试将包含Date的列表AAA与一系列日期进行比较。我想查看列表中是否存在任何日期范围。如果日期存在,我将列表项复制到另一个列表BBB,否则我将空值添加到列表BBB。

我遇到的问题是,根据我的实际代码,我不知道如何不通过while循环的错误语句,直到它到达比较结束。

使用下面的代码,它会在while循环中传递true和false,这会伪造所需的结果。我得到的结果是每次出现的时间都是假的。简而言之,我们可以说列表包含日期为6/5/2010,日期范围为2010年5月5日至2010年7月5日。所以我会在真正的部分创建一个项目,而在ITAL中创建一个错误的部分,这是错误的。存在的日期可以是真实的也可以是错误的。不是两个,所以我创建了两个项目!

如何才能取得正确的结果?任何其他方法或建议请。

我的代码如下:

DateTime StartDate; 
DateTime EndDate;
Datetime tempDate = StartDate;
List<DateTime> dateToEvaluate;

bool TimeIsPresent = false;
foreach (var tempItem in TaskList)
{
    while (EndDate.AddDays(1) != tempDate)
    {
        if (tempItem.Date[0] == tempDate)
        {
            TimeIsPresent = True;
            break;
        }
        else
        {
            if (TimeIsPresent == False)
            {
                if (!(tempDate.DayOfWeek == DayOfWeek.Sunday)
                {
                    dateToEvaluate = new List<DateTime>();
                    dateToEvaluate.Add(tempDate);
                    tempTask.Add(new GroupedTask { ID = null,
                                                   TaskID = null,
                                                   Date = dateToEvaluate });
                 }
             }
         }

         tempDate = tempDate.AddDays(1);
                  }

     if (TimeIsPresent == True)
     {
         tempTask.Add(new GroupedTask { ID = tempItem.ID,
                                        TaskID = tempItem.TaskID,
                                        Date = tempItem.Date });
         TimeIsPresent = false;
     }
 }

让我举个例子。我的日期范围如下:8月8日星期一至8月14日星期日。 现在我的任务列表如下:item1:Date 9Aug,item2:Date 11Aug。

所以我的tempTask必须如下: item1:Date 8月8日,taskID:null,ID:null, item2:Date 8 Aug,taskID:678,ID:7, item3:日期10Aug,taskID:null,ID:null, item4:Date11 Aug,taskID:890,ID:34, item5:Date 8月12日,taskID:null,ID:null, item6:Date 8 Aug,taskID:null,ID:null


第二个例子:

我的日期范围如下:8月8日星期一至8月14日星期日。 现在我的任务列表如下:item1:Date 9Aug,item2:Date 11Aug,item3:Date 14Aug

所以我的tempTask必须如下: item1:Date 8月8日,taskID:null,ID:null, item2:Date 8 Aug,taskID:678,ID:7, item3:日期10Aug,taskID:null,ID:null, item4:Date11 Aug,taskID:890,ID:34, item5:Date 8月12日,taskID:null,ID:null, item6:Date 8 Aug,taskID:null,ID:null, item4:Date14 Aug,taskID:894,ID:74,

4 个答案:

答案 0 :(得分:1)

我认为你制造的东西比实际上更难。据我了解,您正在使用TaskList中的每个项目,并查看日期是否属于某个范围。如果是,则将其添加到另一个列表并转到下一个项目,否则将空白条目添加到另一个列表并继续检查。

如果我的理解是正确的,请尝试:

根据OP的评论编辑

代码现在遍历TaskList中每个项目的整个范围,并添加一个带有日期的空对象或日期的相应任务。

无需使用bool来确定此方案中是否存在日期。

// Note that you'll have to assign values to StartDate and EndDate, otherwise you'll get
// a Null Reference Exception
DateTime StartDate;
DateTime EndDate;
Datetime tempDate = StartDate;
List<DateTime> dateToEvaluate;

foreach (var tempItem in TaskList)
{
    // Reset tempDate to the starting date before each loop
    tempDate = StartDate;

    while (EndDate.AddDays(1) != tempDate)
    {
        if (tempDate.DayOfWeek != DayOfWeek.Sunday)
        {
            if (tempItem.Date[0] == tempDate)
            {
                tempTask.Add(new GroupedTask { ID = tempItem.ID,
                                               TaskID = tempItem.TaskID,
                                               Date = tempItem.Date });
            }
            else
            {
                dateToEvaluate = new List<DateTime>();
                dateToEvaluate.Add(tempDate);
                tempTask.Add(new GroupedTask { ID = null,
                                               TaskID = null,
                                               Date = dateToEvaluate });
            }

        }   

        tempDate = tempDate.AddDays(1);
    }
}

已编辑以添加

假设2周的范围,7/1从星期一开始到7/14。假设有两个任务 - 任务1的日期为7/3,任务2的日期为7/12。我期待tempTask中的以下内容:

26个元素(两个任务项目各13个日期),所有元素都有一个空ID,除了两个任务各一个。

您真的想要一个没有重复的综合列表吗?即,在我的例子中,将有13个元素,2个将具有非空ID?如果两个或多个任务具有相同的日期会发生什么?

我确实发现了一个错误,因为我没有在每个循环之前将tempDate重置为开始。

编辑基于新的理解

好的,所以你试图获得第二个列表,其中包含给定范围内的所有日期,GroupedTask对象将是该日期的现有GroupedTask,或者为null如果没有匹配,则GroupedTask为该日期。

我建议你看看Enigmativity的答案,因为这可能是一个更优雅的解决方案(我没有详细研究过),但这是另一种方法。最大的变化是我翻转了while循环和foreach循环。

// Note that you'll have to assign values to StartDate and EndDate, otherwise you'll get
// a Null Reference Exception
DateTime StartDate;
DateTime EndDate;

// Declare an instance of GroupedTask for use in the while loop
GroupedTask newTask;

Datetime tempDate = StartDate;

// Loop through the entire range of dates
while (EndDate.AddDays(1) != tempDate)
{

    // You included Sundays in your example, but had earlier indicated they
    // weren't needed.  If you do want Sundays, you can remove this outer if
    // block
    if (tempDate.DayOfWeek != DayOfWeek.Sunday)
    {

        // Create a "null" GroupedTask object
        // The Date property in GroupedTask appears to be a List<DateTime>,
        // so I chose to initialize it along with the other properties.
        newTask = new GroupedTask() { ID = null,
                                      TaskID = null,
                                      Date = new List<DateTime>() { tempDate }};

        // For each date in the range, check to see if there are any tasks in the TaskList
        foreach (var tempItem in TaskList)
        {
            // If the current item's date matches the current date in the range,
            // update the newTask object with the current item's values.
            // NOTE:  If more than one item has the current date, the last one in
            // will win as this code is written.
            if (tempItem.Date[0] == tempDate)
            {
                newTask.ID = tempItem.ID;
                newTask.TaskID = tempItem.TaskID;
                newTask.Date = tempItem.Date;
            }
        }

        // Add the newTask object to the second list
        tempTask.Add(newTask);
    }
}

答案 1 :(得分:0)

我不确定 EndDate tempDate 以及您示例中的其他内容。但是,如果您尝试遍历DateRange并检查特定日期的存在,那么您可以考虑以下示例:

    static void yourFunction()
    {
        //
        //Some Stuffs
        //
        foreach (var tempItem in TaskList)
        {
            if (DateRange.Contains(tempItem.Date[0]))
            {
                //Do Task
            }
            else
            {
                //Do Task
            }
        }
        //
        //Some Stuffs
        //
    }
    public static IEnumerable<DateTime> DateRange
    {
        get
        {
            for (DateTime day = startDate; day < EndDate; day = day.AddDays(1))
            {
                yield return day;
            }
        }
    } 

在一个属性上封装一系列日期是 Jon Skeet 的想法,我从他的书C# in Depth中了解到它

答案 2 :(得分:0)

我发现你的代码有点混乱,但如果我理解你的意图,那么我有一个使用LINQ的解决方案。我的方法可能有点令人困惑,但我很乐意帮助你完成它。

我的理解是,您有一系列日期要创建GroupedTask个对象的匹配列表,您将在每个匹配日期从现有TaskList中获取对象范围或如果没有匹配则创建“虚拟”实例。

我假设您已定义StartDate变量以及您在问题中使用的EndDate变量。

我的解决方案(我已经测试过)看起来像这样:

var query = 
    from d in dates
    from t in getTasksForDate(d)
    where (t.ID != null) || (d.DayOfWeek != DayOfWeek.Sunday)
    select t;

tempTask.AddRange(query);

暂时忽略需要定义的两个部分(dates&amp; getTasksForDate),查询的工作方式是从开始到结束运行每个日期并选择该日期的任务(如果日期不存在,则来自TaskList或“虚拟”任务)然后过滤掉星期日的任何“虚拟”任务。然后将任务添加到tempTask列表中。

现在找到缺失的部分。

要获取dates列表,请执行以下操作:

var days = EndDate.Date.Subtract(StartDate.Date).Days + 1;

var dates =
    Enumerable
        .Range(1 - days, days)
        .Select(d => EndDate.AddDays(d));

只要StartDateEndDate之前或之前,您就会有一个日期列表,从StartDate开始到EndDate结束。

getTasksForDate是比较棘手的部分。

您需要先将TaskList列表转换为查找函数,将任何日期转换为该日期的GroupedTask个对象列表。使用LINQ很容易:

var lookup = TaskList.ToLookup(x => x.Date[0].Date, x => new GroupedTask()
{
    ID = x.ID,
    TaskID = x.TaskID,
    Date = x.Date,
});

接下来,您需要创建getTasksForDate函数,该函数将获取日期并返回日期查找中的GroupedTask列表或单个“虚拟”GroupedTask对象这个日期没有任务。

Func<DateTime, IEnumerable<GroupedTask>> getTasksForDate = d =>
{
    return lookup[d].DefaultIfEmpty(new GroupedTask()
    {
        ID = null,
        TaskID = null,
        Date = new List<DateTime>() { d, },
    });
};

就是这样。

如果您想根据StartDate的实际值定义EndDate和/或TaskList,可以使用以下代码:

var StartDate = TaskList.Select(t => t.Date[0].Date).Min();
var EndDate = TaskList.Select(t => t.Date[0].Date).Max();

我在大多数.Date引用之后使用了DateTime来确保该日期没有时间组件。

如果你想进一步解释,请大声说出来。

答案 3 :(得分:0)

如果我明白你要做什么,我会改变你这样做的方式。首先,我会发现你的范围内的所有日期都有一个或多个相关的任务(并将它们放在一个字典中,以便能够让他们知道日期),然后我会创建tempTask。像这样:

        DateTime StartDate;
        DateTime EndDate;
        DateTime tempDate = StartDate;
        List<DateTime> dateToEvaluate;
        Dictionary<DateTime, List<Task>> dateTaskDict = new Dictionary<DateTime, List<Task>>();

        bool TimeIsPresent = false;
        foreach (Task tempItem in TaskList)
        {
            while (EndDate.AddDays(1) != tempDate)
            {
                if (tempItem.Date[0] == tempDate)
                {
                    List<Task> tasksForDate;
                    if (!dateTaskDict.TryGetValue(tempDate, out tasksForDate))
                    {
                        tasksForDate = new List<Task>();
                        dateTaskDict[tempDate] = tasksForDate;
                    }
                    tasksForDate.Add(tempItem);
                    break;
                }
                tempDate = tempDate.AddDays(1);
            }
        }
        tempDate = StartDate;
        while (EndDate.AddDays(1) != tempDate)
        {
            List<Task> tasks;
            if (dateTaskDict.TryGetValue(tempDate, out tasks))
            {
                foreach (Task aTask in tasks)
                    tempTask.Add(new GroupedTask { ID = aTask.ID,
                                               TaskID = aTask.TaskID,
                                               Date = tempDate });
            }
            else
            {
                if (tempDate.DayOfWeek != DayOfWeek.Sunday)
                {
                    tempTask.Add(new GroupedTask { ID = null
                                               TaskID = null,
                                               Date = tempDate });
                }
            }
        }