我正在寻找一个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个对象。任何想法?(
更新对不起,我忘了说我是按降序对数组排序的。所以,是的,数组中的位置不应该对查询有任何影响。
这个怎么样?
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:显然,为了只获得序列的第一个元素,你必须调用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;
不好看,但是给你…
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]);
}
使用内置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;
}
当然,通过使方法通用并将谓词作为参数传递,可以使其更具可重用性,但由于这是一个非常具体的要求,我不确定它会非常有用…