Home > OS >  Merge (add values together, reduce to single element) all pairs in List (except for first and last p
Merge (add values together, reduce to single element) all pairs in List (except for first and last p

Time:10-26

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 Adding 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.

  • Related