0

I am learning LINQ in C#. I have the following JSON data:

[ { "product": [ "a", "b", "c" ] }, { "product": [ "a","b" ] }, { "product": [ "b","c" ] }, { "product": [ "b", "c" ] }, { "product": [ "a","b" ] }, { "product": [ "b", "c" ] }, { "product": [ "a" ] }, ] 

I would like to perform a LINQ by grouping product over its count then order by descending and finally selecting the top 3.

How can I do that? In the result, I have to show the product and its count like below:

 "b","c" 3 "a","b" 2 "a","b","c" 1 

My current code is:

public class Product { public List<string> Name { get; set; } } string json = File.ReadAllText("products.json"); var products = JsonConvert.DeserializeObject<List<Product>>(json); var result = (from p in products .GroupBy(pt => pt.Name) .OrderByDescending(pt => pt.Count()) .SelectMany(pt => pt) select p).Take(3); 

But I am getting all 1 as count. Can you please help to correct the result? Thank you.

5
  • Did you try anything? Commented Mar 18, 2018 at 9:43
  • yes I tried but it came out with all 1. I think I am doing mistake Commented Mar 18, 2018 at 9:47
  • 2
    Than add the code to the question. Commented Mar 18, 2018 at 9:49
  • @Guy I added the code in the question. please check Commented Mar 18, 2018 at 9:56
  • @john please check the question again, I added the code. Commented Mar 18, 2018 at 9:57

1 Answer 1

0

You are trying to group by a sequence but without custom comparator. That will not work.
To achive your desired output try do this:

Define your custom equality comparer:

public class SequenceComparer : IEqualityComparer<string[]> { public bool Equals(string[] x, string[] y) { if (ReferenceEquals(x, y)) return true; if (x == null || y == null) return false; return x.SequenceEqual(y); } public int GetHashCode(string[] obj) { return obj.Aggregate(42, (c, n) => c ^ n.GetHashCode()); } } 

Parse your json to anonymous object

var json = "[\r\n {\r\n \"product\": [\r\n \"a\", \"b\", \"c\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"a\",\"b\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"b\",\"c\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"b\", \"c\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"a\",\"b\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"b\", \"c\"\r\n ]\r\n },\r\n {\r\n \"product\": [\r\n \"a\"\r\n ]\r\n },\r\n]"; var products = JsonConvert.DeserializeAnonymousType(json, new[] {new {product = new string[] { }}}); 

Group by product with your custom equality comparer

var result = products.GroupBy(p => p.product, new SequenceComparer()) .Select(g => new {g.Key, Count = g.Count()}) .OrderByDescending(x => x.Count) .Take(3); 

Now you can see a result:

foreach (var row in result) Console.WriteLine($"{string.Join(",", row.Key)} {row.Count}"); 

will output

'b,c' 3 'a,b' 2 'a,b,c' 1 

Live demo

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much. It worked. :) If you have time, could you please tell me why we need the hash function and how did you calculate the hashcode?
@shahnaj This question may help you to understand why GetHashCode is important. And this question may guide you to "how to calculate"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.