LINQ按日期间隔获取对象

时间:2011-04-16 19:02:38

标签: c# linq linq-to-objects

我正在寻找一个LINQ查询,它只会选择那些日期间隔不超过20秒的对象。例如:

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个对象。任何的想法? :(

更新

抱歉,我忘了提到我正按降序对数组进行排序。所以是的,数组中的位置不应该对查询产生任何影响。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分: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]);
}

答案 2 :(得分: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;
}

当然,通过使方法通用并将谓词作为参数传递,可以使其更具可重用性,但由于这是一个非常具体的要求,我不确定它是否会非常有用...... < / p>