2011-08-10 86 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 }); 
       } 
      } 
     }