Reputation: 1467
I am looking for a way to do the following in LINQ (it is basically a sumproduct where the same array contains both operands of the product at n
and n + 1
indices, obviously the array length is always 2 * n
).
int[] input = { -3, 26, -2, 19, 2, 19, 3, 29, 1, 48 };
// sum product
double result = 0;
for (int i = 0; i < input.Length; i += 2)
result += input[i] * input[i + 1];
// result = 57
// linq version of calculating resultPrice ???
How can I do this (elegantly) with LINQ?
Upvotes: 7
Views: 2635
Reputation: 22876
I am going for the short and confusing version:
int result = input.Select((e, i) => (i & 1) * e * input[i & -2]).Sum(); // 57
Upvotes: 1
Reputation: 18127
var result = Enumerable.Range(0, input.Length/2)
.Select(i => input[i*2] * input[i*2 + 1]).Sum();
This should be enough. Here example in dotNetFiddle.
This code is pretty much mirror of:
for (int i = 0; i < input.Length/2; i++)
result += input[i*2] * input[i*2 + 1];
which is doing the exact same thing as your loop, but instead of step +2
of your loop you have step +1
and loop duration ArrayItems/2
and you make sum of elements from input[i*2] * input[i*2 + 1]
Upvotes: 8
Reputation: 10287
You can Zip
the 2 sub-arrays using multiplications and then Sum
them, just as you would explain the request:
int result = input.Where((x, i) => i % 2 == 0)
.Zip(input.Skip(1).Where((x, i) => i % 2 == 0), (x, y) => x * y)
.Sum();
If you have MoreLinq
referenced you can have a cleaner solution by folding every batch of 2 items into their product and using Sum
:
var res2 = input.Batch(2)
.Select(z => z.Fold((x, y) => x * y))
.Sum();
Or a more generic solution by using Aggregate
instead of Fold
:
var res2 = input
.Batch(2)
.Select(batch => batch.Aggregate(1, (x, y) => x * y))
.Sum();
Upvotes: 8
Reputation: 32296
You can use the overload of Select
that includes the index, then group on the index divided by 2. Aggregate the values by multiplying them, and finally do a sum.
int[] input = { -3, 26, -2, 19, 2, 19, 3, 29, 1, 48 };
var result = input.Select((v, i) => new { Index = i, Value = v })
.GroupBy(x => x.Index / 2, x => x.Value)
.Select(g => g.Aggregate(1, (v, a) => a *= v))
.Sum();
Console.WriteLine(result);
This will also work for more general cases where you want to sum the produce of n consecutive numbers by dividing by n instead of 2.
Upvotes: 6