我有以下收藏
// The collection to query
var stageTable = new List<Stage>
{
new Stage {StageId = 1, LifecycleId = 1, StageSeqNo = 1},
new Stage {StageId = 2, LifecycleId = 1, StageSeqNo = 2},
new Stage {StageId = 3, LifecycleId = 1, StageSeqNo = 3},
new Stage {StageId = 4, LifecycleId = 1, StageSeqNo = 4},
new Stage {StageId = 5, LifecycleId = 2, StageSeqNo = 1},
new Stage {StageId = 6, LifecycleId = 2, StageSeqNo = 2},
new Stage {StageId = 7, LifecycleId = 2, StageSeqNo = 3},
new Stage {StageId = 8, LifecycleId = 2, StageSeqNo = 4},
};
我尝试构建一个查询,该查询将返回给定Stage
的下一个currentStage
,但包含在LifecycleId
定义的同一子集中,例如,给定{ {1}}我希望currentStage = 2
返回Stage
,但stageId = 3
我会期望currentStage = 4
返回null
切换为LifecycleId
价值2
。
这就是我所拥有的
var lifecycleId = stageTable
.Where(x => x.StageId == currentStageId)
.Select(x => x.LifecycleId);
var nextStage = stageTable
.Where(s => s.LifecycleId == lifecycleId.First())
.SkipWhile(s => s.StageId != currentStageId)
.Skip(1).FirstOrDefault();
它似乎有效,但有没有办法在单个查询中执行此操作?
答案 0 :(得分:1)
这使用带有谓词的FirstOrDefault的重载:
{
var currentStageId = 3;
// The collection to query
var stageTable = new List<Stage> {
new Stage {StageId = 1, LifecycleId = 1, StageSeqNo = 1},
new Stage {StageId = 2, LifecycleId = 1, StageSeqNo = 2},
new Stage {StageId = 3, LifecycleId = 1, StageSeqNo = 3},
new Stage {StageId = 4, LifecycleId = 1, StageSeqNo = 4},
new Stage {StageId = 5, LifecycleId = 2, StageSeqNo = 1},
new Stage {StageId = 6, LifecycleId = 2, StageSeqNo = 2},
new Stage {StageId = 7, LifecycleId = 2, StageSeqNo = 3},
new Stage {StageId = 8, LifecycleId = 2, StageSeqNo = 4},
};
var nextStage = stageTable.FirstOrDefault(s => s.StageId > currentStageId && s.LifecycleId == stageTable.FirstOrDefault(s2=>s2.StageId==currentStageId)?.LifecycleId);
}
答案 1 :(得分:1)
如果您安装MoreLINQ NuGet package,则可以使用以下代码:
var currentStageId = 4;
var nextStage = stageTable.SkipWhile(z => z.StageId < currentStageId)
.Lead(1, (x, y) => new { existing = x, next = y })
.Take(1)
.FirstOrDefault(z => z.next?.LifecycleId == z.existing.LifecycleId)?.next;
Console.WriteLine(nextStage?.StageId);
SkipWhile
将跳过当前行之前的数据。
Lead
将合并相邻的行(即将当前行和下一行放在一起)。
Take 1
将确保我们只获得一行(代表当前行和下一行)。
如果第二行与第一行没有相同的FirstOrDefault
,LifeCycleId
将确保返回null。
答案 2 :(得分:0)
一种方法是首先获得当前阶段和下一阶段(无论周期如何),然后检查下一阶段是否属于同一周期:
var nextStage = stageTable.Where(s => s.StageId >= currentStageId) //filter out all lower values
.OrderBy(s=> s.StageId) //if the list is always ordered, this could be omitted
.Take(2) //enumeration now contains the currentid and the next id
.GroupBy(s=>s.LifecycleId) //only from those 2 objects -> group by the lifecycle
.First().Skip(1).FirstOrDefault(); //the (first) group will only contain 2 items, if the lifecycle is the same
答案 3 :(得分:0)
我将介绍一种方法来迭代底层枚举和(可能为null)前一项:
@Test
可以使用此扩展程序提出以下解决方案:
public static class EnumerableExtras
{
public static IEnumerable<Pair<T>> WithPrevious<T>(this IEnumerable<T> source)
where T : class
{
T previous = null;
foreach (var item in source)
{
yield return new Pair<T>(item, previous);
previous = item;
}
}
}
public class Pair<T> where T : class
{
public Pair(T current, T previous)
{
Current = current;
Previous = previous;
}
public T Current { get; }
public T Previous { get; }
}
对于值类型,可以使用可为空的var nextStage = stageTable
.WithPrevious()
.FirstOrDefault(pair => pair.Previous?.StageId == currentStageId &&
pair.Current.LifecycleId == pair.Previous?.LifecycleId)
?.Current;
属性定义相似的Pair<>
类。