Goal
Reduce the total length of a list by merging pairs in the list (except the first and last pair) into single elements.
Visual Example
I have a single dimension list, which looks somewhat like this:
Pair (A) | Pair (B) | Pair (C) | Pair (D) |
---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|
12.0 | 10.0 | 19.0 | 34.0 | 16.0 | 12.0 | 99.0 | 68.0 |
An example of what I would like the list (or a new list) to look like instead:
Pair (A) | Pair (B) | Pair (C) |
---|
0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|
12.0 | 10.0 | 53.0 | 28.0 | 99.0 | 68.0 |
Still a single dimension list but the total length has been reduced by merging pairs of elements (ignoring the first and last pair) into a single element (instead of a pair of elements), with a new value calculated by adding the former pairs values together.
Theory
Using some combination of GetRange
, Select
, Aggregate
and Where
to either alter the original list, or return a new list somehow.
In-closing
I'd like to apologise for the dodgy wording, and formatting of my question: I'm obviously out of my depth in what I'm trying to achieve - any help would be greatly appreciated.
Cheers.
CodePudding user response:
Sounds fairly simple to do with a loop
var outList = new List<int>();
outList.Add(inList[0]);
outList.Add(inList[1]);
for(int x = 2; x < inList.Count -2;x =2){
outList.Add(inList[x] inList[x 1]);
}
outList.Add(inList[^2]);
outList.Add(inList[^1]);
You take the first two elements unchanged, you then run a loop that skips in twos summing a pair of elements together and Add
ing the result to the outList, stopping short of processing the last 2 entries, then add those verbatim to the outList
If the intent was to modify the original list, work backwards in twos between the end and the start
for(int x = list.Count - 4; x >= 2;x-=2){
list[x] = list[x 1];
list.RemoveAt(x 1);
}
By working backwards, our manipulations (removing from the list) doesn't affect future elements we have yet to process as the list shortens, which makes the logic a bit easier
--
LINQ's a hammer; not every problem is a nail.. If you can only accept LINQ then it could look like:
list.Take(2).Concat(
list.Skip(2)
.Take(list.Count-4)
.Select((e, i) => new { E = e, N = i/2 })
.GroupBy(x => x.N, x => x.E)
.Select(g => g.Sum())
).Concat(
list.Skip(list.Count-2)
).ToList();
Or with ranges:
list[..2].Concat(
list[2..^2]
.Select((e, i) => new { E = e, N = i/2 })
.GroupBy(x => x.N, x => x.E)
.Select(g => g.Sum())
).Concat(
list[^2..]
).ToList();
Take the first 2, add on the result of taking the middle N values, projecting them including their index and grouping on index/2 then summing the resulting group, then Concat on the last 2. I don't like it as much as the loops. I can think of other linq ways too, but none I really like.