Find sequence in IEnumerable using Linq

后端 未结 5 1383
醉酒成梦
醉酒成梦 2020-12-03 23:01

What is the most efficient way to find a sequence within a IEnumerable using LINQ

I want to be able to create an extension method which allows

5条回答
  •  一整个雨季
    2020-12-03 23:38

    I understand this is an old question, but I needed this exact method and I wrote it up like so:

    public static int ContainsSubsequence(this IEnumerable elements, IEnumerable subSequence) where T: IEquatable
    {
        return ContainsSubsequence(elements, 0, subSequence);
    }
    
    private static int ContainsSubsequence(IEnumerable elements, int index, IEnumerable subSequence) where T: IEquatable
    {
        // Do we have any elements left?
        bool elementsLeft = elements.Any();
    
        // Do we have any of the sub-sequence left?
        bool sequenceLeft = subSequence.Any();
    
        // No elements but sub-sequence not fully matched
        if (!elementsLeft && sequenceLeft)
            return -1; // Nope, didn't match
    
        // No elements of sub-sequence, which means even if there are
        // more elements, we matched the sub-sequence fully
        if (!sequenceLeft)
            return index - subSequence.Count(); // Matched!
    
        // If we didn't reach a terminal condition,
        // check the first element of the sub-sequence against the first element
        if (subSequence.First().Equals(e.First()))
            // Yes, it matched - move onto the next. Consume (skip) one element in each
            return ContainsSubsequence(elements.Skip(1), index + 1 subSequence.Skip(1));
        else
            // No, it didn't match. Try the next element, without consuming an element
            // from the sub-sequence
            return ContainsSubsequence(elements.Skip(1), index + 1, subSequence);
    }
    

    Updated to not just return if the sub-sequence matched, but where it started in the original sequence.

    This is an extension method on IEnumerable, fully lazy, terminates early and is far more linq-ified than the currently up-voted answer. Bewarned, however (as @wai-ha-lee points out) it is recursive and creates a lot of enumerators. Use it where applicable (performance/memory). This was fine for my needs, but YMMV.

提交回复
热议问题