Home > Software design >  LINQ groupby, divide and extract
LINQ groupby, divide and extract

Time:04-21

My program is storing same fetched data in a list of tuples

public List<Tuple<int, double, double, double, double>> Temp = new List<Tuple<int, double, double, double, double>>();

Take this as and example

Temp.Add(new Tuple<int, double, double, double, double>(1, 1.1, 0.4, 0, 100.1));
Temp.Add(new Tuple<int, double, double, double, double>(2, 1.1, 0.4, 1.1, 99.1));
Temp.Add(new Tuple<int, double, double, double, double>(2, 1.1, 0.4, 1.3, 55.1));
Temp.Add(new Tuple<int, double, double, double, double>(1, 2.2, 0.4, 0, 100.2));
Temp.Add(new Tuple<int, double, double, double, double>(2, 2.2, 0.4, 1.1, 50.2));

I have to summarize the data so that the Tuples that have the same T2 and T3 are returned with their T4 and their T5 divided by the T5 of the first tuple that has that T2 and T3.

If we look at the example, the first 3 tuples have the same T2 and T3, so my end result would be

[2, 1.1, 0.4, 1.1, (99.1/100.1)] //<- the 2nd tuple with its T5 divided by the 1st tuple T5
[2, 1.1, 0.4, 1.3, (55.1/100.1)] //<- the 3rdtuple with its T5 divided by the 1st tuple T5

Then the 4th and 5th tuples also have the same T2 and T3, so:

[2, 2.2, 0.4, 1.1, (50.2/100.2)] //<- the 5th tuple with its T5 divided by the 4th tuple T5

I am stuck at:

var norm_result = Temp.GroupBy(x => new { x.Item2, x.Item3 })
    .Select(x => new
    {
        AA = x.Key.Item2,
        BB = x.Key.Item3,
        CC = ??, //Item4
        DD = ??, // Item5 divided by its first value in the group
    });

CodePudding user response:

Each group in your GroupBy statement has a collection of the items in that group, and the Key of that group, so when calculating your norm results you need to enumerate through each group to do your calculations.

var norm_result = Temp.GroupBy(x => new{ x.Item2, x.Item3 })
    //Since this select statement returns IEnumerables for each grouping
    //this will be an IEnumerable of IEnumerables. If you want to flatten
    //things into a single IEnumerable you could do a SelectMany here.
    .Select(x =>
    {
        //sort by Item1, hopefully the order of the items after the first
        //doesn't matter since they all seem to be a value of 2.
        var sorted = x.OrderBy(item => item.Item1).ToList();
        //this is the first item in the group that has Item1 == 1
        var first = sorted[0];
        //skip the first since it appears that you are wanting to skip
        //the first value in your norm results and the select here will
        //return an IEnumerable of the remaining items in the group with
        //the dividing logic
        return sorted.Skip(1).Select(item => new
        {
            item.Item1,
            item.Item2,
            item.Item3,
            item.Item4,
            Item5 = item.Item5 / first.Item5
        });
    });
  • Related