通过一个属性相交多个列表

时间:2019-01-09 12:28:50

标签: c# sql .net linq intersect

我有List<List<ProductFilter>>

public class ProductFilter
{
    public int Id { get; set; }
    public int FilterValueId { get; set; }
    public int ProductId { get; set; }
    public int? FilterId { get; set; }
    public string FilterValue { get; set; }
    public string FilterName { get; set; }
}

我想要Intersect之前的ProductId并返回ProductFilter。有可能吗 我尝试:

var intersection = groupList
  .Aggregate((previousList, nextList) => previousList
     .Select(x => x.ProductId)
     .Intersect(nextList.Select(x => x.ProductId))
  .ToList());

但是它给了我错误,因为返回int

  

无法隐式转换类型'System.Collections.Generic.List<int>'   到“ System.Collections.Generic.List<ProductFilter>

2 个答案:

答案 0 :(得分:1)

您正在收到上述错误,因为对于AggregateList<ProductFilter>的这种特定重载,累加器函数将返回与源中元素相同的类型。而不是List<int>

要产生IEnumerable<int>作为结果,请先将项目投影到IEnumerable<int>,然后调用Aggregate

groupList.Select(p => p.Select(e => e.ProductId))
         .Aggregate((previousList, nextList) => previousList.Intersect(nextList));

答案 1 :(得分:0)

为此,您必须使用Intersect的重载,该重载接受IEqualityComparer<>

class ProductFilterProductIdEqualityComparer : IEqualityComparer<ProductFilter>
{
    public bool Equals(ProductFilter x, ProductFilter y)
    {
        if (ReferenceEquals(x, y))
            return true;
        if (ReferenceEquals(x, null))
            return false;
        if (ReferenceEquals(y, null))
            return false;
        return x.ProductId == y.ProductId;
    }

    public int GetHashCode(ProductFilter obj) => obj.ProductId;
}
var productFilterProductIdEqualityComparer = new ProductFilterProductIdEqualityComparer();
var intersection = groupList
    .Aggregate((previousList, nextList) => 
        previousList.Intersect(nextList, productFilterProductIdEqualityComparer)
    .ToList());

注意:请记住,当两个ProductFilter具有相同的ProductId但在其他属性上不同时,您只会在intersection中得到第一个属性< / p>