5

我有一个包含 96 个值的集合。我想对 4 个顺序索引的值求和。如何使用 Linq 做到这一点?

例子

collection = {100, 101, 200, 150, 103, 105, 100, 104,  .........., 20, 40, 60, 80};

Sum of (100, 101, 200, 150;)then sum of (103, 105, 100, 104;)... then sum of(20, 40, 60, 80;)这意味着现在我的新集合将有 24 个值。

如何使用 Linq 做到这一点?

4

6 回答 6

11

我们可以从这个实用函数开始,Batch根据给定的批量大小添加项目:

public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
    List<T> buffer = new List<T>(batchSize);

    foreach (T item in source)
    {
        buffer.Add(item);

        if (buffer.Count >= batchSize)
        {
            yield return buffer;
            buffer = new List<T>(batchSize);
        }
    }
    if (buffer.Count > 0)
    {
        yield return buffer;
    }
}

之后就很简单了:

var query = data.Batch(4)
    .Select(batch => batch.Sum());
于 2013-06-11T17:46:07.630 回答
4

您可以分组index/4以获取总和,如下所示:

var res = collection
    .Select((v,i) => new {v, i})
    .GroupBy(p => p.i / 4)
    .Select(g => g.Sum(p.v));
于 2013-06-11T17:49:27.263 回答
3

您可以根据索引计算组索引,对其进行分组,然后从每个组中的值中获取总和:

var sums = collection
.Select((n, i) => new { Group = i / 4, Value = n })
.GroupBy(x => x.Group)
.Select(g => g.Sum(y => y.Value));
于 2013-06-11T17:49:37.357 回答
1

首先,找到一种按索引对集合进行分组的方法。在这种情况下,我选择使用整数除法来使元素 0-3 组 0、4-7 组 1 等。

接下来,将您的元素分组到需要求和的不同集合中(通过分组键)。

最后,选择属于每个组的元素的总和。

values.Select((x, i) => new { GroupingKey = i/4, Value = x })
      .GroupBy(x => x.GroupingKey)
      .Select(x => new { Group = x.Key, Sum = x.Sum() });
于 2013-06-11T17:52:15.180 回答
1

您将需要一个新的扩展方法Partition

public static IEnumerable<IEnumerable<T>> Partition<T>(
    this IEnumerable<T> source, int partitionSize)
{
    var counter = 0;
    var result = new T[partitionSize];
    foreach(var item in source)
    {
        result[counter] = item;
        ++counter;
        if(counter >= partitionSize)
        {
            yield return result;
            counter = 0;
            result = new T[partitionSize];
        }
    }

    if(counter != 0)
        yield return result.Take(counter);
}

用法是:

collection.Partition(4).Select(x => x.Sum())

这是ServyBatch发布的方法的另一种方法。

于 2013-06-11T17:51:09.717 回答
0

这样做:

static IEnumerable<int> BatchSum(int batchSize, IEnumerable<int> collection)
{
    var batch = collection.Take(batchSize).ToList();
    if (batch.Count == 0) yield break;

    yield return batch.Sum();

    var rest = collection.Skip(batchSize);
    foreach (var sum in BatchSum(batchSize, rest)) yield return sum;
}

并使用它:

var collection = new[] { 100, 101, 200, 150, 103, 105, 100, 104, 20, 40, 60, 80, 11, 13 };

foreach (var sum in BatchSum(4, collection)) Show(sum);

输出将是:

551
412
200
24

如您所见,您的收藏长度不必是batchSize.

于 2013-06-11T18:52:09.603 回答