我正在设计一个界面,用户可以在其中加入一个关键字的公告,当他们这样做时,我想建议通常与所选关键字一起出现的其他关键字。诀窍是将相关频率与建议关键字的属性一起使用。
关键字类型(EF)包含以下字段:
int Id
string Text
string UrlString
......以及与出版物实体集的多对多关系 我快到了。随着:
var overlappedKeywords =
selectedKeyword.Publications.SelectMany(p => p.Keywords).ToList();
这里我得到了一些非常有用的东西:一个扁平的关键字列表,每个关键字都在列表中重复,但很多时候它与selectedKeyword一起出现。
剩余的挑战:
因此,我希望计算每个关键字在此列表中出现的次数,并将不同的关键字实体投影到名为KeywordCounts的新类型上,该类型与关键字具有相同的字段,但还有一个字段:int PublicationsCount
,我将在其中填充overlappedKeywords中每个关键字的计数。 我该怎么做?
到目前为止,我尝试了两种方法:
var keywordCounts = overlappingKeywords
.Select(oc => new KeywordCount
{
KeywordId = oc.Id,
Text = oc.Text,
UrlString = oc.UrlString,
PublicationsCount = overlappingKeywords.Count(ok2 => ok2.Id == oc.Id)
})
.Distinct();
... PublicationsCount正在填充,但是Distinct在这里不起作用。 (必须我为此创建了一个EqualityComarer?为什么默认的EqualityComarer不起作用?)
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = ???
Text = ???
UrlString = ???
PublicationsCount = ???
})
我对GroupBy不是很清楚。我似乎没有任何访问“选择”中的“o”,并且c不符合关键字的任何属性
更新
我的第一种方法适用于传递给.Distinct()的简单EqualityComparer:
class KeywordEqualityComparer : IEqualityComparer<KeywordCount>
{
public bool Equals(KeywordCount k1, KeywordCount k2)
{
return k1.KeywordId== k2.KeywordId;
}
public int GetHashCode(KeywordCount k)
{
return k.KeywordId.GetHashCode();
}
}
......但Slauma的答案更可取(并被接受)因为它不需要这个。我仍然难以理解为EF实体实例的默认EqualityComparer是什么 - 它不会仅仅根据主要ID进行比较,就像我在上面所做的那样?
答案 0 :(得分:1)
你第二次尝试是更好的方法。我认为完整的代码是:
var keywordCounts = overlappingKeywords
.GroupBy(o => o.Id)
.Select(c => new KeywordCount
{
Id = c.Key,
Text = c.Select(x => x.Text).FirstOrDefault(),
UrlString = c.Select(x => x.UrlString).FirstOrDefault(),
PublicationsCount = c.Count()
})
.ToList();
这是对象的LINQ,我想,因为似乎没有涉及EF上下文而是对象overlappingKeywords
,所以分组发生在内存中,而不是在数据库中。