假设我有一个清单
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)
所以,我必须取连续值并将它们分组到列表中.
您可以创建扩展方法(我在这里省略了源检查),它将迭代源并创建连续项目组。如果源中的下一项不连续,则生成当前组:
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)