使用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做到这一点?

我们可以从这个实用程序function开始,根据给定的批量大小Batch项目:

 public static IEnumerable> Batch(this IEnumerable source, int batchSize) { List buffer = new List(batchSize); foreach (T item in source) { buffer.Add(item); if (buffer.Count >= batchSize) { yield return buffer; buffer = new List(batchSize); } } if (buffer.Count > 0) { yield return buffer; } } 

之后它就像下面这样简单:

 var query = data.Batch(4) .Select(batch => batch.Sum()); 

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

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

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

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

你需要一个新的扩展方法Partition

 public static IEnumerable> Partition( this IEnumerable 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方法的另一种方法。

首先,设置一种按索引对集合进行分组的方法。 在这种情况下,我选择使用整数除法来生成元素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() }); 

这样做:

 static IEnumerable BatchSum(int batchSize, IEnumerable 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一个因素。