简体   繁体   中英

Select Distinct rows when only one columns is different Linq

I have a data = List<Model> , where Model looks like this

public class Model{
    public string String1 { get; set; }
    public int Int1{ get; set; }
    public int Int2{ get; set; }
    public string String2 { get; set; }
    public decimal Decimal1{ get; set; }
    ...
    public decimal DecimalN{ get; set; }
}

I want to have average of each DecimalX values group by String1 , Int1 , Int2 , but my problem is that sometimes I have two or more the same rows and only String2 is different, so I would like to do Distinct , but doesn't work because of this String2 property. I was trying to change all values of String2 to null or empty string

var x = data.ForEach(x => x.String2= null);

but I receive error Cannot asign void to implicitly- typed variable.

ForEach does not return anything - it's is void method, so your assignment to x is not valid. Instead of this:

var x = data.ForEach(x => x.String2= null);

You should do like this:

data.ForEach(x => x.String2= null);

Just like Reniuz said that error occurs becaus forEach doesn't return anything (void).

Returning to your main problem, you mentioned that you need the average value for each Decimal.

For Decimal1 you can do something like this:

var b = list.GroupBy(g => new { g.String1, g.Int1, g.Int2 }).Select(r=> new {r.Key.String1, r.Key.Int1, r.Key.Int2, avgDecimal1 = r.Select(g=>g.Decimal1).Average()}).ToList();

First you need to Group by the elements that are going to be your keys (without String2 like you said) and after that, select those keys and the AVG of the elements of a determined property (eg Decimal1). You can add more AVG functions if you want (avgDecimal2, avgDecimal3, etc)

you want to start with projecting your results with the values you want to work with or in the way you want to work with them.

var query = source.Select(e => new
{
    e.String1,
    e.Int1,
    e.Int2,
    e.Decimal1,
});

Just omit the properties you don't want.

// or go straight to your average
var sum = data.GroupBy(e => new
{
    e.String1,
    e.Int1,
    e.Int2,
    e.Decimal1,
}).Average(e => e.Key.Decimal1);

I don't understand why you want distinct values. May be you can provide an example. One solution can be -

  var result = data.GroupBy(x => new { x.String1, x.Int1, x.Int2 })
                        .Select(g => new
                        {
                            String1 = g.Key.String1,
                            Int1 = g.Key.Int1,
                            Int2 = g.Key.Int2,
                            AvgDecimal1 = g.Select(x => x.Decimal1).Average(),
                            AvgDecimal2 = g.Select(x => x.Decimal1).Average(),
                            AvgDecimalN = g.Select(x => x.Decimal1).Average()
                        }).ToList();

If you want distinct values you can add distinct before group by -

 data.Select(d => new Model { String1 = d.String1, Int1 = d.Int1, Int2 = d.Int2, Decimal1 = d.Decimal1, Decimal2 = d.Decimal2, DecimalN = d.DecimalN }) //returning new collection with String2 as null
                    .Distinct()

First solution produces following result - 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM