LINQ 按日期间隔获取对象

发布于 2024-11-01 23:18:34 字数 1156 浏览 1 评论 0原文

我正在寻找一个 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 个对象。有什么想法吗? :(

更新

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

I'm looking for a LINQ query that will select only those objects whose date interval is not higher than 20 seconds. For example:

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 }
};

I want to select only the first occurence of those objects whose date interval is not longer than 20 seconds against the next object. In this case, the query should return only the first 4 objects. Any idea? :(

UPDATE

Sorry, I forgot to mention that I'm sorting the array by descending order. So yes, the position in the array shouldn't have any effect on the query.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橘香 2024-11-08 23:18:34

这又如何呢?

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;

What about this?

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;

EDIT: Obviously you have to call First() in order to get only the first element of the sequence.

query.First();

EDIT 2: I have just read you are ordering your results descending. In this case the query will be slightly different:

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;
绝情姑娘 2024-11-08 23:18:34

它不太漂亮,但是你看吧...

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]);
}

It ain't pretty, but here you go...

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);

Does it have to be LINQ? I love LINQ, but I think something like this would be more readable...

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]);
}
北座城市 2024-11-08 23:18:34

可能可以使用内置的 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;
}

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

It is probably possible to do it using built-in Linq operators, but in this case I think writing a specific method is easier. You could do something like that:

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;
}

Of course it would be possible to make it more reusable, by making the method generic and passing a predicate as a parameter, but since it's a very specific requirement, I'm not sure it would be very useful...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文