使用LINQ对数字进行分组

3
假设我有一个数字列表,就像这样:

   [3, 3, 1, 2, 3, 2]

我希望你能帮我将它们分成若干个组,并使得每个组的总和小于或等于五。正确答案是:

  [3], [3, 1], [2,3], [2]

有没有使用Linq表达这个的方法?
3个回答

9
简单易懂。
var results = xs.Aggregate<int, List<List<int>>>(
    new List<List<int>> { new List<int>() },
    (a, n) =>
    {
        if (a.Last().Sum() + n > 5)
        {
            a.Add(new List<int> { n });
        }
        else
        {
            a.Last().Add(n);
        }
        return a;
    });

所以,从这个角度来看:
var xs = new [] { 3, 3, 1, 2, 3, 2, };

我得到了这个:

结果


非常狡猾,我喜欢它。唯一的潜在缺点是在每次向前迈进时对Last()列表中先前值的重复求和。对于大目标组总和(比如10000),可能会变慢,但对于目标为5的情况来说还好。 - Baldrick

0

不知道这是否与您想要的接近,但让我们试一试吧。

List<int> l = new List<int> { 3, 3, 1, 2, 3, 2 };
int[] index = {0};
var s = l.Select((k, i) =>
{
    if (i < index[0])
        return null;

    int total = 0;
    return l.Skip(index[0]).TakeWhile(x =>
    {
        total += x;
        if (total <= 5)
            index[0]++;
        return total <= 5;
    });
}).Where(x => x != null);

foreach (IEnumerable<int> e in s)
{
    foreach (int i in e)
    {
        Console.Write("{0},", i);
    }
    Console.WriteLine();
}

我的推理如下:

  1. 我们必须遍历所有项目,因此选择。
  2. 我们必须从列表中取出项目,直到达到总数,因此采用TakeWhile。
  3. 我们必须跟踪我们在列表中的位置,因此使用索引和返回null。

我尝试使用int index = 0;最初,但Resharper抱怨访问修改的闭包并建议将其更改为int[] index = {0};


0
你可以尝试使用扩展方法(类似这样的东西,已经使用你的示例进行了测试,但是除此之外没有进行更多的测试!):
public static class Extensions
{
    public static IEnumerable<IEnumerable<int>> GroupsLessThan(this IEnumerable<int> source, int target)
    {
        var list = new List<int>();
        var runningCount = 0;
        foreach (var element in source)
        {
            if (runningCount + element < target)
            {
                list.Add(element);
                runningCount += element;
            }
            else
            {
                yield return list;
                runningCount = element;
                list = new List<int>{element};
            }
        }

        if (list.Count > 0)
        {
            yield return list;
        }
    }
}

使用方法如下:

var array = new int[] { 3, 3, 1, 2, 3, 2 };
var list = array.GroupsLessThan(6).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接