2013-03-04 269 views
0

我想從dateRange獲取所有日期值,其中每個日期時間是DayOfWeek.Friday,.. Monday,.. Sunday與LINQ比較2列表

相交併沒有工作,因爲我猜那些2所列出不是真正的交叉點......和他們有不同的類型:日期時間與Enum.DayOfWeek

這給了我唯一的全星期五,但我也想週一,週日......不使用OR運算符。

var dateRange = _dateService.GetDateRange(startDate, endDate).Where(d => visibleWeekDays.Any(v => d.DayOfWeek == v)).ToList(); 

這些都是我的列表必須以某種方式比較:

IEnumerable<DateTime> dateRange = _dateService.GetDateRange(startDate, endDate); 
IEnumerable<DayOfWeek> visibleWeekDays = new List<DayOfWeek> 
{ 
    DayOfWeek.Friday, 
    DayOfWeek.Monday, 
    DayOfWeek.Sunday, 
}; 

請不要寫全靈查詢作爲解決方案。 只需以隨機順序編寫linq擴展方法,我必須使用它來解決謎題。 只是爲了玩意兒和學習的緣故:)

UPDATE

看到我輸入的日期時間值,我想輸出:

enter image description here

但要知道,visibleWeekDays列表不靜態的。這個集合中可以有一個動態的數值。因此,我可以也不想使用& &或||運營商。

+0

你能解釋一下你正在試圖完成什麼?你能告訴我預期的I/O是什麼嗎? – 2013-03-04 20:15:33

+0

它不適合以隨機順序給出答案。這個問題可能對未來的讀者有益。我編輯了您的問題以刪除該評論。 – 2013-03-04 20:18:11

+0

看到我的答案,它會提供您定義的輸出。 – Oliver 2013-03-04 20:24:18

回答

1

當你發現自己在想一個路口的位置,但在類型的兩個集合的是不一樣的,它通常意味着你要Join。根據定義,交集是一個連接,其中兩個集合是相同類型的,其中鍵選擇符是「自身」,並且結果選擇器只是隨機選擇其中一個項目(因爲它們必須相等,交點的定義)。由於並非所有這些限制都適用於您,您所需要做的就是走出更爲廣泛的Join

正如這個演示,這裏是使用Intersect的實現只是Join

public static IEnumerable<T> Intersect<T>(this IEnumerable<T> first 
    , IEnumerable<T> second, IEqualityComparer<T> comparer) 
{ 
    return first.Join(second, x => x, x => x, (a, b) => a, comparer); 
} 

DayOfWeek可以只選擇自己作爲一個鍵,然後你只需要得到一個DayOfWeek對象的方法在密鑰選擇器的DateTime之外。對於你的結果選擇器,你只需要抓取DateTime對象;你不應該需要DayOfWeek對象了。

每當你看到自己寫的有Where(x => collection.Any(...Contains或內部的Where賠率是你應該使用Join相反,其他一些搜索操作的LINQ解決方案,如果適用(你至少應該問問自己,如果你要使用Join)。

既然你不想要一個完整的實現,我會把它放在一個擾流標籤下面。不要看它,如果你希望自己編寫的代碼:

public static IEnumerable FilterDaysOfWeek(IEnumerable dates 
    , IEnumerable daysOfWeek) 
{ 
    return dates.Join(daysOfWeek 
     , date => date.DayOfWeek 
     , day => day 
     , (date, day) => date); 
}

+0

是的,那麼它很容易使用查詢風格:var query =從日期範圍內的d 加入v在可見週日在d.DayOfWeek等於v 選擇新{VisibleDate = d}; – Elisabeth 2013-03-04 20:46:07

+0

@Elisa你不需要/想創建一個新的匿名對象來保存日期。只需'選擇d'並完成。除此之外,是的,這將工作得很好。關於是否不使用查詢與方法語法,大多是個人偏好。 – Servy 2013-03-04 20:48:27

+0

啊對...我習慣使用ext方法風格,幾乎從不使用查詢風格。但通過連接,查詢風格更容易。我更喜歡你的解決方案通過contains()/ Any(),因爲它在語義上似乎更正確和明顯是怎麼回事:) – Elisabeth 2013-03-04 20:51:06

0

如果您將DayOfWeek轉換爲整數,您可以執行簡單的>和<比較來獲取有效的值,因此只需在某處查詢應該很好。

0

如果你想獲得的所有日期的GetDateRange有匹配那些visibleWeekdays你可以使用下面的LINQ語句DayOfWeek

_dateService.GetDateRange(startDate, endDate) 
      .Where(d=> visibleWeekdays.Contains(d.DayOfWeek)); 

下面是這個動作的完整測試:

class Test 
    { 
     static void Main(string[] args) 
     { 
      var weekdays = new[] { DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday }; 
      var result = GetDateRange(DateTime.Today, DateTime.Today.AddDays(14)) 
       .Where(d => weekdays.Contains(d.DayOfWeek)); 
     } 

     public static IEnumerable<DateTime> GetDateRange(DateTime start, DateTime end) 
     { 
      DateTime date = start; 

      do 
      { 
       yield return date; 
       date = date.AddDays(1); 
      } 
      while (date < end); 
     } 
    } 
+0

您是否閱讀過我的非工作示例.Any()與Contains()的行爲相同。它只返回星期五的...... – Elisabeth 2013-03-04 20:26:03

+0

我明白了,GetDateRange在做什麼?它絕對是輸出正確的日期嗎? – Oliver 2013-03-04 20:28:48

+0

它從startDate到endDate獲取日期時間值。沒有過濾。 – Elisabeth 2013-03-04 20:31:55

0

您可以在Where子句中的visibleWeekDays上使用Contains

+0

這可能會使代碼看起來更清潔一些,但它不會有任何不同。 – Servy 2013-03-04 20:28:53

+0

@Servy:「Any」版本很難閱讀,「Contains」不是。 OP沒有要求一個不同的功能版本,只是一個工作版本。 'Join'具有不同的語義,但考慮到內部列表的大小,優化後的版本可能使用簡單的內部列表,從而使差異最小化。 – Guvante 2013-03-04 20:46:10