LINQ中的条件GroupBy()

时间:2016-11-24 10:04:58

标签: c# linq matrix guid

我正在使用填充了项目之间相似性的矩阵。我将这些保存为数据库中的对象列表。 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子句分组第一个或第二个索引?

如果我要详细说明,请告诉我!

2 个答案:

答案 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()