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.
You are trying to group by a sequence but without custom comparator. That will not work.
To achive your desired output try do this:
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());
}
}
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[] { }}});
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
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.