2011-04-16 66 views
2

我正在查找LINQ查询,该查询将仅选择那些日期间隔不超过20秒的对象。例如:LINQ按日期间隔获取对象

AuthenticationEssay[] essays = new AuthenticationEssay[] { 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(20), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(24), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(29), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(38), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(125), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(347), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(400), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(422), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(446), Success = false }, 
    new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(467), Success = false } 
}; 

我想只选择那些对象,它们的日期间隔的第一次出现是不大于针对下一个对象20秒。在这种情况下,查询应只返回前4个对象。任何想法? :(

UPDATE

对不起,我忘了提,我被按降序排序的数组。所以,是的,在阵列中的位置应该不会对查询产生任何影响。

+0

如果最后一项是“AddSeconds(465)',而不是将它包括在内? – 2011-04-16 19:14:24

+1

你的意思是日期间隔不超过20秒?你的意思是DateTime.Now和essay [i] .Date之间的区别吗?你是指短文[0]和短文[1]之间的意思? – mfanto 2011-04-16 19:14:26

+0

我的意思是散文[0]和散文[1]之间。但在做出一些比较之前,我正在对数组进行排序 – Davita 2011-04-16 19:26:34

回答

1

这个怎么样

var query from i in Enumerable.Range(1, count - 1) 
      let current = list[i] 
      let previous = list[i - 1] 
      // I see some empty positions in your example, nullability check 
      where current != null && previous != null 
      where (current.Date - previous.Date).TotalSeconds < 20 
      select previous; 

编辑:?很明显,你必须调用First()为了只获取序列的第一个元素

query.First(); 

编辑2:我刚刚看过你订购你的结果降序。在这种情况下,查询会稍有不同:

var query from i in Enumerable.Range(1, count - 1) 
      let current = list[i] 
      let previous = list[i - 1] 
      // I see some empty positions in your example, nullability check 
      where current != null && previous != null 
      where (previous.Date - current.Date).TotalSeconds < 20 
      select current; 
+0

不,不起作用。它返回太多不应该在列表中的对象 – Davita 2011-04-16 19:38:59

+0

如果您只想要第一个元素,请在此LINQ查询上调用'First()'方法。 – 2011-04-16 19:40:37

+0

谢谢,但我知道如何得到元素的第一次出现。我想要的是首次发生日期间隔不超过20秒的元素。 – Davita 2011-04-16 19:49:27

0

它不漂亮,但在这里你去...

var result = Enumerable.Range(0, essays.Count() - 1) 
    .Select(i => new {Essays1 = essays[i], Essays2 = essays[i + 1]}) 
    .Where(a => a.Essays2 != null) 
    .Where(a => a.Essays2.Date - a.Essays1.Date < new TimeSpan(0, 0, 0, 20)) 
    .Select(a => a.Essays1); 

是否必须是LINQ?我爱LINQ,但我认为这样的事情会更可读......

var result = new List<AuthenticationEssay>(); 
for (var i = 0; i < (essays.Count() - 1); i++) 
{ 
    if (essays[i + 1] != null) 
     if (essays[i + 1].Date - essays[i].Date < new TimeSpan(0, 0, 0, 20)) 
      result.Add(essays[i]); 
} 
0

中很可能使用做内置的LINQ的运营商,但在这种情况下,我觉得写一个特定的方法是比较容易。你可以做这样的事情:

static IEnumerable<AuthenticationEssay> Filter(IEnumerable<AuthenticationEssay> list) 
{ 
    AuthenticationEssay last = null; 
    AuthenticationEssay previous = null; 
    foreach(var item in list) 
    { 
     if (last == null) 
     { 
      // Always return the first item 
      yield return item; 
     } 
     else if ((item.Date - last.Date).TotalSeconds >= 20) 
     { 
      yield return item; 
     } 

     previous = last; 
     last = item; 
    } 
    if (previous != null && last != null && (last.Date - previous.Date).TotalSeconds <= 20) 
     yield return last; 
} 

当然,这将有可能使其更可反复使用,使得该方法的通用和传递一个谓词作为参数,但因为它是一个非常具体的要求,我不知道它会非常有用...

相关问题