假设我有一个清单
var listOfInt = new List<int> {1, 2, 3, 4, 7, 8, 12, 13, 14}
如何使用LINQ获取列表列表,如下所示:
{{1, 2, 3, 4}, {7, 8}, {12, 13, 14}}
所以,我必须取连续值并将它们分组到列表中.
您可以创建扩展方法(我在这里省略了源检查),它将迭代源并创建连续项目组。如果源中的下一项不连续,则生成当前组:
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;
        }                
    }
}
用法很简单:
var listOfInt = new List<int> { 1, 2, 3, 4, 7, 8, 12, 13, 14 };
var groups = listOfInt.ToConsecutiveGroups();
结果:
[
  [ 1, 2, 3, 4 ],
  [ 7, 8 ],
  [ 12, 13, 14 ]
]
更新:这是此扩展方法的通用版本,它接受谓词来验证两个值是否应被视为连续:
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;
        }                
    }
}
用法很简单:
var result = listOfInt.ToConsecutiveGroups((x,y) => (x == y) || (x == y - 1));
| 归档时间: | 
 | 
| 查看次数: | 410 次 | 
| 最近记录: |