使用Linq按索引求和

时间:2013-06-11 17:43:10

标签: c# .net linq

我有一个有96个值的集合。我想总结4个连续索引的值。我怎么能用Linq做到这一点?

实施例

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

(100, 101, 200, 150;)之和,然后(103, 105, 100, 104;)的总和...然后(20, 40, 60, 80;)的总和这意味着现在我的新集合将有24个值。

如何使用Linq执行此操作?

6 个答案:

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

答案 1 :(得分:4)

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

var res = collection
    .Select((v,i) => new {v, i})
    .GroupBy(p => p.i / 4)
    .Select(g => g.Sum(p.v));

答案 2 :(得分:3)

您可以从索引,组中计算组索引,并从每组中的值中获取总和:

var sums = collection
.Select((n, i) => new { Group = i / 4, Value = n })
.GroupBy(x => x.Group)
.Select(g => g.Sum(y => y.Value));

答案 3 :(得分: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())

这是Servy发布的Batch方法的替代方法。

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

答案 5 :(得分: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的因素。