将 IEnumerable<T> 拆分为 IEnumerable<IEnumerable<T>>(不进行缓存)

and*_*ykx 1 c#

我想知道是否可以编写一个函数,将序列拆分为返回为 的子序列IEnumerables,其中如果当前T等于T该子序列的第一个子序列,则子序列结束,而不缓存子序列。我已经成功编写了一个在列表中构建当前子序列的实现。

所以我希望能够实现功能

IEnumerable<IEnumerable<T>> SplitInSubsequences(IEnumerable<T> sequence)
{
   ... 
}
Run Code Online (Sandbox Code Playgroud)

不使用一些临时集合List<T>来缓存当前子序列。

为了说明分割操作应该做什么:

var sequence = new List<int>{ 1,2,3,1,  4,6,1,5,4,  1,3,1, 2,2};
var subsequences = SplitInSubsequences( sequence ).ToList();
Assert.That(subsequences.Length,Is.EqualTo(4));
Assert.That(subsequences[0],Is.EquivalentTo(new List<int>{1,2,3,1});
Assert.That(subsequences[1],Is.EquivalentTo(new List<int>{4,6,6,5,4});
Assert.That(subsequences[2],Is.EquivalentTo(new List<int>{1,3,1});
Assert.That(subsequences[3],Is.EquivalentTo(new List<int>{2,2});
Run Code Online (Sandbox Code Playgroud)

请注意,原则上仅需要存储每个子序列的第一个元素以便与当前元素进行比较。

Ser*_*rvy 7

几乎总是如此,当您想要流式传输时,IEnumerable<T>您应该使用迭代器块。如果您想要嵌套流,只需嵌套迭代器块即可。

public static IEnumerable<IEnumerable<T>> SplitInSubsequences<T>(IEnumerable<T> sequence, IEqualityComparer<T> comparer = null)
{
    comparer ??= EqualityComparer<T>.Default;
    using IEnumerator<T> iterator = sequence.GetEnumerator();
    while (iterator.MoveNext())
    {
        T startOfGroup = iterator.Current;
        yield return NextGroup();

        IEnumerable<T> NextGroup()
        {
            yield return startOfGroup;

            while (iterator.MoveNext())
            {
                yield return iterator.Current;

                if (comparer.Equals(iterator.Current, startOfGroup))
                {
                    yield break;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)