Using Linq to search for the next item in a subset of a list

I have the following collection

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

and I'm trying to build a query that returns the next Stageone given by a currentStage, but contained in the same subset that is defined LifecycleId, for example, given currentStage = 2, I would expect to receive Stagefrom stageId = 3back, but with currentStage = 4I expect to get nullback, since it LifecycleIdswitches to a value 2.

This is what I have

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

It seems to work, but is there a way to accomplish this in a single request?

+4
source share
4 answers

This uses the FirstOrDefault overload, which takes Predicate:

{
    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
source

MoreLINQ NuGet , :

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 , null , LifeCycleId, ).

+1

- ( ), , :

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
0

, (, ) :

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<> nullable Previous.

0

Source: https://habr.com/ru/post/1683953/


All Articles