使用LINQ拆分数组

mih*_*i.b 6 c# linq list

假设我有一个清单

var listOfInt = new List<int> {1, 2, 3, 4, 7, 8, 12, 13, 14}
Run Code Online (Sandbox Code Playgroud)

如何使用LINQ获取列表列表,如下所示:

{{1, 2, 3, 4}, {7, 8}, {12, 13, 14}}
Run Code Online (Sandbox Code Playgroud)

所以,我必须取连续值并将它们分组到列表中.

Ser*_*kiy 3

您可以创建扩展方法(我在这里省略了源检查),它将迭代源并创建连续项目组。如果源中的下一项不连续,则生成当前组:

public static IEnumerable<List<int>> ToConsecutiveGroups(
    this IEnumerable<int> source)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        else
        {                    
            int current = iterator.Current;
            List<int> group = new List<int> { current };

            while (iterator.MoveNext())
            {
                int next = iterator.Current;
                if (next < current || current + 1 < next)
                {
                    yield return group;
                    group = new List<int>();                            
                }

                current = next;
                group.Add(current);
            }

            if (group.Any())
                yield return group;
        }                
    }
}
Run Code Online (Sandbox Code Playgroud)

用法很简单:

var listOfInt = new List<int> { 1, 2, 3, 4, 7, 8, 12, 13, 14 };
var groups = listOfInt.ToConsecutiveGroups();
Run Code Online (Sandbox Code Playgroud)

结果:

[
  [ 1, 2, 3, 4 ],
  [ 7, 8 ],
  [ 12, 13, 14 ]
]
Run Code Online (Sandbox Code Playgroud)

更新:这是此扩展方法的通用版本,它接受谓词来验证两个值是否应被视为连续:

public static IEnumerable<List<T>> ToConsecutiveGroups<T>(
    this IEnumerable<T> source, Func<T,T, bool> isConsequtive)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }
        else
        {                    
            T current = iterator.Current;
            List<T> group = new List<T> { current };

            while (iterator.MoveNext())
            {
                T next = iterator.Current;
                if (!isConsequtive(current, next))
                {
                    yield return group;
                    group = new List<T>();                            
                }

                current = next;
                group.Add(current);
            }

            if (group.Any())
                yield return group;
        }                
    }
}
Run Code Online (Sandbox Code Playgroud)

用法很简单:

var result = listOfInt.ToConsecutiveGroups((x,y) => (x == y) || (x == y - 1));
Run Code Online (Sandbox Code Playgroud)