2011-08-10 53 views
0

我想比较一个包含日期和日期范围的日期的AAA列表。我想查看是否有任何日期范围存在于列表中。如果日期存在,我将列表项目复制到另一个列表BBB,否则我将空值添加到列表BBB。While循环难度

我遇到的问题是,用我的实际代码,我不知道如何不通过while循环的虚假陈述,直到它达到比较结束。

使用下面的代码,它会在while循环中传递true和false两个参数,这会伪造所需的结果。我所获得的结果是每一次出现的时候,我都有同样的错误。简而言之,可以说列表中包含日期为2010年5月5日,日期范围为2010年4月5日至7/5/2010。所以我会在真实部分创建一个项目,并创建一个项目创建错误部分,这是错误的。目前的日期可以是真实或虚假的部分。不是两个,这样我就有两件物品了!

我该如何达到正确的结果?请任何其他方法或suggetsion。

我的代码如下:

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:日期9ug,item2:日期11ug。

所以我tempTask必须如下: 物品1:日期8月8日,任务id:空,ID:空, ITEM2:日期8月9日,任务id:678,ID:7, 项目3:日期10Aug,任务id: null,ID:null, item4:Date11 Aug,taskID:890,ID:34, item5:Date 12 Aug,taskID:null,ID:null, item6:Date 13 Aug,taskID:null,ID:null


第二个例子:

我的日期范围如下:周一至8月8日 - 桑德唉8月14日 现在我的任务列表如下:项目1:日期9Aug,ITEM2:日期11Aug,项目3:日期14Aug

所以我tempTask必须如下: 物品1:日期8月8日,任务id:空,ID :null, item2:日期9 Aug,taskID:678,ID:7, item3:Date10ug,taskID:null,ID:null, item4:Date11 Aug,taskID:890,ID:34, item5:Date 8月12日,任务id:空,ID:空, ITEM6:日期8月13日,任务id:空,ID:空, ITEM4:Date14八月,任务id:894,编号:74,

+2

为什么不使用'bool'作为TimeIsPresent,并将其设置为'false'? –

+5

你知道,如果你将'TimeIsPresent'定义为一个'bool',你不需要'true'和'false'的引号 - 事实上,你可以使用'if(TimeIsPresent)'或'if(! TimeIsPresent)'代替。 – Gabe

+0

EndDate来自哪里,为什么你要重新计算'EndDate.AddDays(1)'? – R0MANARMY

回答

0

我不知道是什么是结束日期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; 
      } 
     } 
    } 

封装了一系列对房地产的日期是乔恩斯基特的想法 ,我从他的书中学到了C# in Depth

+0

Date DateRange进入无限循环! – learning

+0

对不起,浪费你的时间与错误!由于'DateTime'是不可变的,因此简单地将'day.AddDays(1)'放在循环中不会受到影响。我们需要增加日期,例如'day = day.AddDays(1)'。我更新了我的代码。 – NaveenBhat

+0

非常感谢,你指导我解决问题。感谢所有试图帮助我的人! – learning

1

我觉得你让事情比实际上更加困难。据我了解,你正在采取TaskList每个项目,看看日期是否在一定范围内。如果是,则将其添加到另一个列表并转到下一个项目,否则将空白条目添加到另一个列表并继续检查。

如果我的理解是正确的,试试这个:

基于OP的评论EDITED

代码现在经过在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 ,如果没有匹配,则为该日期的空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); 
    } 
} 
+0

谢谢@Tim,我想你还没有明白我想达到的目标。使用您的代码,您正在循环查看列表,直到找到范围内的日期,这不是我想要的!使用您的代码,一旦您从列表中的范围中找到日期,并且之后的所有其他日期都将被忽略,它就会停止。我想要的是将范围内的所有日期(星期日除外,列表taskList没有星期日的日期)添加到列表tempTask,并根据它在列表中的值,将值复制到temptask else它将值复制为null,如我的示例中所示。 – learning

+0

@学习 - 请参阅我的编辑。在您列出的场景中,如果找到日期,则不需要将布尔值设置为true - 只需评估每个日期,然后添加相应的任务项或空任务项即可。 – Tim

+0

谢谢@Tim,此代码既不能解决问题。假设我的日期是2010年6月5日 - 星期一,7/5/2010 - 星期二,8/5/2010,9/5/2010 - 星期三(例如,虚构的日期)在我的塔克列表中。您的代码只读取任务列表中的值6/5/2010,其他值被忽略(具有空值)!您的tempTask代码结果将只包含6/5/2010的值,这不是预期的结果!尽管tempTask包含所有其他日期,但它不包含任务列表值! – learning

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

只要StartDate是或EndDate之前,你会现在有开始对StartDateEndDate结束日期的列表。

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

就是这样。

如果你想根据从TaskList您可以使用此代码的实际值来定义StartDate和/或EndDate

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

我大部分DateTime引用后使用.Date,以确保没有时间组件到日期。

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

0

如果我明白你想要做什么,我会改变你这样做的方式。首先,我会查找范围内所有具有一个或多个关联任务的日期(并将它们放在Dictionary中以便能够让他们知道日期),然后创建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 }); 
       } 
      } 
     }