分区/分割/部分IEnumerable <T>进入IEnumerable <IEnumerable <T >>基于使用LINQ的函数?

a d*_*per 5 linq data-partitioning

我想使用LINQ将C#中的序列拆分为一系列序列.我做了一些调查,我发现的最接近的SO文章与略有关系.

但是,这个问题只询问如何根据常量值对原始序列进行分区.我想根据操作对我的序列进行分区.

具体来说,我有一个包含十进制属性的对象列表.

public class ExampleClass
{
    public decimal TheValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

假设我有一个序列ExampleClass,并且相应的值序列TheValue是:

{0,1,2,3,1,1,4,6,7,0,1,0,2,3,5,7,6,5,4,3,2,1}
Run Code Online (Sandbox Code Playgroud)

我想将原始序列划分为IEnumerable<IEnumerable<ExampleClass>>具有TheValue类似值的值:

{{0,1,2,3}, {1,1,4,6,7}, {0,1}, {0,2,3,5,7}, {6,5,4,3,2,1}}
Run Code Online (Sandbox Code Playgroud)

我只是迷失了如何实现这一点.那么,你能帮忙吗?

我现在有一个非常难看的解决方案,但有一种"感觉",LINQ将增加我的代码的优雅.

Jon*_*eet 6

好的,我想我们可以做到这一点......

public static IEnumerable<IEnumerable<TElement>>
    PartitionMontonically<TElement, TKey>
    (this IEnumerable<TElement> source,
     Func<TElement, TKey> selector)
{
    // TODO: Argument validation and custom comparisons
    Comparer<TKey> keyComparer = Comparer<TKey>.Default;

    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        TKey currentKey = selector(iterator.Current);
        List<TElement> currentList = new List<TElement> { iterator.Current };
        int sign = 0;
        while (iterator.MoveNext())
        {
            TElement element = iterator.Current;
            TKey key = selector(element);
            int nextSign = Math.Sign(keyComparer.Compare(currentKey, key));

            // Haven't decided a direction yet
            if (sign == 0)
            {
                sign = nextSign;
                currentList.Add(element);
            }
            // Same direction or no change
            else if (sign == nextSign || nextSign == 0)
            {
                currentList.Add(element);
            }
            else // Change in direction: yield current list and start a new one
            {
                yield return currentList;
                currentList = new List<TElement> { element };
                sign = 0;
            }
            currentKey = key;
        }
        yield return currentList;
    }
}
Run Code Online (Sandbox Code Playgroud)

完全未经测试,但我认为它可能有用......