2013-03-04 266 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