-1

I have some problems in executing a Linq query with the group by clause in a C# project as follows:

public class Stock {
    public string Name {get; set;}
    public List<int> Values {get; set;}
    public float Price {get; set;}
}

// Stock collection
List<Stock> stocks = new List<Stock>()
{
    new Stock(){Name="Prod1", Values=new List<int>{1, 2, 3, 0}, Price=5.0f, 
    new Stock(){Name="Prod1", Values=new List<int>{1, 2, 3, 0}, Price=5.0f,
    new Stock(){Name="Prod11", Values=new List<int>{1, 0, 3, 1}, Price=8.0f,
    new Stock(){Name="Prod11", Values=new List<int>{1, 0, 3, 1}, Price=8.0f,
    new Stock(){Name="Prod18", Values=new List<int>{0, 0, 4, 1}, Price=4.5f,
    new Stock(){Name="Prod20", Values=new List<int>{4, 0, 0, 2}, Price=9.9f,
    new Stock(){Name="Prod20", Values=new List<int>{4, 0, 0, 2}, Price=9.9f,
    new Stock(){Name="Prod29", Values=new List<int>{2, 1, 0, 1}, Price=7.2f,
};

var query = stocks.GroupBy(x => x, (x, g) => new { Count = g.Count(), Values = x}).ToList();

This query gives wrong grouping results.

ekad
  • 14,436
  • 26
  • 44
  • 46
murtzi
  • 11
  • 2
  • 1
    Please provide an example of input data and expected grouping results. – Wiktor Stribiżew Mar 17 '15 at 15:38
  • You should write what do you expect (i.e. the correct result) and what you actually get from the code (i.e. the wrong result). This would help us to understand your problem and answer your question. – Jan Spurny Mar 17 '15 at 15:38
  • You are right. I added sample data. – murtzi Mar 18 '15 at 08:44
  • The sample data produce correct results. – Gert Arnold Mar 18 '15 at 12:38
  • The query does not give grouped data. It produces 8 items again. Please check the query.Count() again. Thanks. – murtzi Mar 18 '15 at 13:15
  • 2
    It does give grouped data. The point is: you never defined "wrong" (i.e. expected vs. actual) despite people clearly asking for it. Even now I don't know what you expect. Count() is always 1. To me, given your query, that's correct. – Gert Arnold Mar 18 '15 at 21:25

1 Answers1

2

In order for GroupBy to produce a grouping, the object by which you group must have an override of GetHashCode and Equals, or you need to provide a suitable equality comparer to GroupBy.

Your Stock does not override GetHashCode/Equals, and your GroupBy query does not use a custom equality comparer, so you get unexpected results.

Providing suitable overrides will fix this problem:

public class Stock {
    public string Name {get; set;}
    public List<int> Values {get; set;}
    public float Price {get; set;}
    public override bool Equals(object obj) {
        if (obj == this) return true;
        var other = obj as Stock;
        if (other == null) return false;
        return Name.Equals(other.Name)
            && Price == other.Price
            && Values.SequenceEqual(other.Values);
    }
    public override int GetHashCode() {
        return Name.GetHashCode()
             + Price.GetHashCode()
             + Values.Sum();
    }
}

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523