我正在用 C# 学习 LINQ。我有以下 JSON 数据:
[
{
"product": [
"a", "b", "c"
]
},
{
"product": [
"a","b"
]
},
{
"product": [
"b","c"
]
},
{
"product": [
"b", "c"
]
},
{
"product": [
"a","b"
]
},
{
"product": [
"b", "c"
]
},
{
"product": [
"a"
]
},
]
我想通过将产品分组到其计数来执行 LINQ然后按降序排序,最后选择前 3 名。
我该怎么做?在结果中,我必须显示产品及其计数,如下所示:
"b","c" 3
"a","b" 2
"a","b","c" 1
我当前的代码是:
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);
但我得到了所有 1 作为计数。你能帮忙纠正结果吗?谢谢。
您正在尝试按序列分组,但没有自定义比较器。那行不通。
要获得所需的输出,请尝试执行以下操作:
定义自定义相等比较器:
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());
}
}
将 json 解析为匿名对象
var json = "[rn {rn "product": [rn "a", "b", "c"rn ]rn },rn {rn "product": [rn "a","b"rn ]rn },rn {rn "product": [rn "b","c"rn ]rn },rn {rn "product": [rn "b", "c"rn ]rn },rn {rn "product": [rn "a","b"rn ]rn },rn {rn "product": [rn "b", "c"rn ]rn },rn {rn "product": [rn "a"rn ]rn },rn]";
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);
现在您可以看到一个结果:
foreach (var row in result)
Console.WriteLine($"{string.Join(",", row.Key)} {row.Count}");
将输出
'b,c' 3
'a,b' 2
'a,b,c' 1
现场演示