假设我有一个列表
var listOfInt = new List<int> {1, 2, 3, 4, 7, 8, 12, 13, 14}
如何使用LINQ获取列表列表,如下所示:
{{1, 2, 3, 4}, {7, 8}, {12, 13, 14}}
所以,我必须取连续值并将它们分组到列表中。
答案 0 :(得分:3)
这适用于已排序和未排序的列表:
var listOfInt = new List<int> { 1, 2, 3, 4, 7, 8, 12, 13 };
int index = 0;
var result = listOfInt.Zip(listOfInt
.Concat(listOfInt.Reverse<int>().Take(1))
.Skip(1),
(v1, v2) =>
new
{
V = v1,
G = (v2 - v1) != 1 ? index++ : index
})
.GroupBy(x => x.G, x => x.V, (k, l) => l.ToList())
.ToList();
外部index
正在构建具有1
值差异的连续组的索引。那么你可以简单地GroupBy
关于这个索引。
为了澄清解决方案,以下是此集合在没有分组(GroupBy
注释)的情况下的外观:
答案 1 :(得分:3)
您可以创建扩展方法(我省略了源检查),它将迭代源并创建连续项组。如果source中的下一个项目不是连续的,则会产生当前组:
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));
答案 2 :(得分:2)
假设您的输入按顺序,以下内容将起作用:
var grouped = input.Select((n, i) => new { n, d = n - i }).GroupBy(p => p.d, p => p.n);
如果您的输入是例如,则无效{ 1, 2, 3, 999, 5, 6, 7 }
。
你会得到{ { 1, 2, 3, 5, 6, 7 }, { 999 } }
。
答案 3 :(得分:0)
这有效:
var results =
listOfInt
.Skip(1)
.Aggregate(
new List<List<int>>(new [] { listOfInt.Take(1).ToList() }),
(a, x) =>
{
if (a.Last().Last() + 1 == x)
{
a.Last().Add(x);
}
else
{
a.Add(new List<int>(new [] { x }));
}
return a;
});
我得到了这个结果: