我正在使用填充了项目之间相似性的矩阵。我将这些保存为数据库中的对象列表。 Similarity对象如下所示:
public class Similarity
{
public virtual Guid MatrixId { get; set; } //The id of the matrix the similarity is in
public virtual Guid FirstIndex { get; set; } //The id of the item of the left side of the matrix
public virtual Guid SecondIndex { get; set; } //The id of the item of the top side of the matrix
public virtual double Similarity { get; set; } //The similarity
}
用户可以查看这些项目。我想要检索与用户已审阅的项目“相似”的项目列表。问题在于我无法确定该项目的ID是在FirstIndex
还是SecondIndex
。我已经编写了一些代码来完成我想要的东西,但是我想知道这是否可以在1个语句中使用。
var itemsNotReviewed = Similarities.Where(x => !itemsReviewed.Contains(x.SecondIndex))
.GroupBy(x => x.SecondIndex)
.ToList();
itemsNotReviewed.AddRange(Similarities.Where(x => !itemsReviewed.Contains(x.FirstIndex))
.GroupBy(x => x.FirstIndex)
.ToList());
其中itemsReviewed
是用户已审核的项目的guid列表,其中Similarities
是与用户审核的项目类似的所有项目的列表。我使用此函数检索该列表:
return (from Row in _context.SimilarityMatrix
where itemIds.Contains(Row.FirstIndex) || itemIds.Contains(Row.SecondIndex)
select Row)
.Distinct()
.ToList();
其中itemIds
是用户已审核过的项目的guid列表。
有没有办法根据Where子句分组第一个或第二个索引?
如果我要详细说明,请告诉我!
答案 0 :(得分:1)
我会改变您原始列表的来源方式:
_context.SimilarityMatrix.Where(Row => itemIds.Contains(Row.FirstIndex) || itemIds.Contains(Row.SecondIndex))
.Select(r => new { r.MatrixId, r.FirstIndex, r.SecondIndex, r.Similarity, MatchingIndex = itemIds.Contains(r.FirstIndex) ? r.FirstIndex : r.SecondIndex })
.Distinct()
.ToList();
这样您只需按匹配索引进行分组。
var itemsNotReviewed = Similarities.
.GroupBy(x => x.MatchingIndex)
.ToList();
您可能希望在动态对象之后转换为Similarity类,或者只是更改类以包含匹配索引。
您可以通过以下方式将它们转换为您的相似类型:
var itemsNotReviewed = Similarities.
.GroupBy(x => x.MatchingIndex)
.Select(g => new { g.Key, Values = g.Values.Select(d => new Similarity { MatrixId = d.MatrixId, FirstIndex = d.FirstIndex, SecondIndex = d.SecondIndex, Similarity = d.Similarity }).ToList() })
.ToList();
答案 1 :(得分:0)
怎么样?
(from x in Similarities
let b2 = !itemsReviewed.Contains(x.SecondIndex)
let b1 = !itemsReviewed.Contains(x.FirstIndex)
where b1 || b2
groupby b2 ? x.SecondIndex : x.FirstIndex into grp
select grp)
.ToList()
let语句引入了一个存储boolean的新的tempoary变量。你当然也可以内联其他功能:
(from x in (from Row in _context.SimilarityMatrix
where itemIds.Contains(Row.FirstIndex) || itemIds.Contains(Row.SecondIndex)
select Row)
.Distinct()
.ToList()
let b2 = !itemsReviewed.Contains(x.SecondIndex)
let b1 = !itemsReviewed.Contains(x.FirstIndex)
where b1 || b2
groupby b2 ? x.SecondIndex : x.FirstIndex into group
select group)
.ToList()
如果您想使用非LINQ语法,您可能需要引入一些匿名类型:
Similarities
.Select(s => new
{
b2 = !itemsReviewed.Contains(x.SecondIndex),
b1 = !itemsReviewed.Contains(x.FirstIndex),
s
})
.Where(a => a.b1 || a.b2)
.GroupBy(a => a.b2 ? a.s.SecondIndex : a.s.FirstIndex, a => a.x) //edit: to get same semantics, you of course also need the element selector
.ToList()