使用linq对相邻值进行分组

时间:2014-12-03 18:32:31

标签: .net linq group-by aggregate

我有一个int值的排序列表,我想组成相邻的值。下一个值为nextvalue> = prevValue + 1的值是邻居。

例如: 列表:

{1,2,3,5,6,8,9,10}

小组将:

{1,2,3}
{5,6}
{8,9,10}

可以使用linq完成吗?

这可以很容易地在没有linq的情况下完成 - 通过迭代列表,但我想知道linq是否有解决方案。

4 个答案:

答案 0 :(得分:1)

如果您必须使用Linq,则可以考虑使用Aggregate方法。

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; 
});

答案 1 :(得分:1)

这对我有用:

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;
        });
}

enter image description here

答案 2 :(得分: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;
            });

我得到了这个结果:

result

作为旁注,我喜欢养成建立像new [] { item }.ToList()这样的列表的习惯,因为它允许构建匿名类型的列表。在许多LINQ查询中非常有用。

答案 3 :(得分:0)

我只有一个非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;
}