.net 使用linq对相邻值进行分组
我有一个整型值的排序列表,我想让组与值相邻。下一个值为nextvalue>=prevValue+1的值是相邻值 例如: 名单: 小组将包括:.net 使用linq对相邻值进行分组,.net,linq,group-by,aggregate,.net,Linq,Group By,Aggregate,我有一个整型值的排序列表,我想让组与值相邻。下一个值为nextvalue>=prevValue+1的值是相邻值 例如: 名单: 小组将包括: {1,2,3} {5,6} {8,9,10} 这可以用linq实现吗 这可以很容易地在没有linq的情况下完成-通过迭代列表,但我想知道linq是否对此有解决方案。我只有一个非linq解决方案(如果我正确理解了问题)。希望能有帮助 void Main() { var list = new List<int>{1,2,3,5,6,8,9
{1,2,3}
{5,6}
{8,9,10}
这可以用linq实现吗
这可以很容易地在没有linq的情况下完成-通过迭代列表,但我想知道linq是否对此有解决方案。我只有一个非linq解决方案(如果我正确理解了问题)。希望能有帮助
void Main()
{
var list = new List<int>{1,2,3,5,6,8,9,10};
GetData(list).Dump();
}
public IEnumerable<List<int>> GetData(IEnumerable<int> data)
{
int prev = 0;
var g = new List<int>();
foreach (var item in data)
{
if(item - prev > 1 && g.Count > 0)
{
yield return g;
g = new List<int>();
}
g.Add(item);
prev = item;
}
yield return g;
}
void Main()
{
var list=新列表{1,2,3,5,6,8,9,10};
GetData(list.Dump();
}
公共IEnumerable GetData(IEnumerable数据)
{
int prev=0;
var g=新列表();
foreach(数据中的var项)
{
如果(项目-上一个>1和&g.计数>0)
{
收益率g;
g=新列表();
}
g、 增加(项目);
prev=项目;
}
收益率g;
}
< /代码> 如果您必须使用LINQ,可以考虑<代码>聚合< /代码>方法。< /P>
x.Aggregate(new List<List<int>> { new List<int>() }, (soFar, next) => {
if (soFar.Last().Contains(next - 1)) {
soFar.Last().Add(next);
} else {
soFar.Add(new List<int> { next });
}
return soFar;
});
x.Aggregate(新列表{new List()},(soFar,next)=>{
if(soFar.Last().Contains(next-1)){
soFar.Last().Add(下一步);
}否则{
添加(新列表{next});
}
返回索法尔;
});
这对我很有用:
private static void GroupToNeighboursTest()
{
var numbers = new List<int> { 1, 2, 3, 5, 6, 8, 9, 10 };
var neighbours = numbers
.Zip(numbers.Skip(1), Tuple.Create)
.Aggregate(new List<List<int>> { new List<int> { numbers.First() } }, (result, i) =>
{
if (i.Item1 == i.Item2 - 1)
{
result.Last().Add(i.Item2);
}
else
{
result.Add(new List<int> { });
result.Last().Add(i.Item2);
}
return result;
});
}
private static void GroupToNeighboursTest()
{
变量编号=新列表{1,2,3,5,6,8,9,10};
var=数字
.Zip(number.Skip(1),Tuple.Create)
.Aggregate(新列表{new List{numbers.First()}},(结果,i)=>
{
如果(i.Item1==i.Item2-1)
{
result.Last().Add(i.Item2);
}
其他的
{
结果.添加(新列表{});
result.Last().Add(i.Item2);
}
返回结果;
});
}
这对我来说很有用:
var result =
items
.Skip(1)
.Aggregate(
new [] { items.Take(1).ToList() }.ToList(),
(acc, item) =>
{
if (acc.Last().Last() == item - 1)
{
acc.Last().Add(item);
}
else
{
acc.Add(new [] { item }.ToList());
}
return acc;
});
我得到这个结果:
顺便说一句,我确实喜欢养成这样的习惯:创建列表new[]{item}.ToList()
,因为它允许创建匿名类型的列表。在许多LINQ查询中非常有用。LINQ是要求吗?是的,LINQ是要求。您确定条件正确吗?如果nextvalue>=prevValue+1
则3和5是邻居:prevVal=3,nextVal=5->prevVal+1=4->5>=4为真,因此prevVal=3和nextVal=5是邻居。它不应该是:nextvalue==prevValue+1
?包含
是一个O(n)操作。另外,这似乎在开始时返回了一个额外的空组。我认为,根据我对问题的理解,您可以将.Contains(…)
行更改为if(soFar.Last().Last()==next-1){
。我刚刚测试了这段代码,它没有生成问题中要求的输出。
var result =
items
.Skip(1)
.Aggregate(
new [] { items.Take(1).ToList() }.ToList(),
(acc, item) =>
{
if (acc.Last().Last() == item - 1)
{
acc.Last().Add(item);
}
else
{
acc.Add(new [] { item }.ToList());
}
return acc;
});