对象列表和对象列表的相交列表

时间:2016-01-14 14:07:44

标签: c# linq

我有一个交易类列表:

class Transactions
{
    public Transactions()
    {
        Products = new List<Product>();
    }

    public string Date { get; set; }

    public string TransactionID { get; set; }

    public List<Product> Products { get; set; }
}

产品类别:

class Product
{
    public decimal ProductCode { get; set; }
}

我有一个像这样的产品列表:

List<Product> unioned = product.Union(secondProduct).ToList();

我想要工会和交易产品的Intersect, 此代码不起作用:

var intersection = transactions.Where(q => q.Products.Intersect(unioned).Any());

我认为原因是交易产品长度是变化的,并且联合长度是固定的。

我该怎么做?

4 个答案:

答案 0 :(得分:3)

Intersect使用默认的相等比较器,因此将进行引用检查 - 即比较对象引用是否相同。

您需要use the overload which allows you to specify an equality comparer

因此:

public class ProductComparer : IEqualityComparer<Product>
{
    public bool Equals(Product x, Product y)
    {
        // TODO - Add null handling.
        return x.ProductCode == y.ProductCode;
    }

    public int GetHashCode(Product obj)
    {
        return obj.ProductCode.GetHashCode();
    }
}

然后:

var intersection = transactions
                  .Where(q => q.Products.Intersect(unioned, new ProductComparer()).Any());

此测试现在将通过:

[TestMethod]
public void T()
{
    Product p = new Product { ProductCode = 10M };
    List<Product> product = new List<Product> { p };
    List<Product> secondProduct = new List<Product> { new Product { ProductCode = 20M } };
    List<Product> unioned = product.Union(secondProduct).ToList();
     var transaction = new Transactions();
     // add a different object reference
     transaction.Products.Add(new Product { ProductCode = 10M }); 

     IList<Transactions>  transactions = new List<Transactions> { transaction };

     var intersection = transactions
                  .Where(q => q.Products.Intersect(unioned, new ProductComparer()).Any());

     Assert.AreEqual(1, intersection.Count());
}

答案 1 :(得分:0)

尝试使用此解决方案而不使用Intersect。我使用ProductCode检查Product是否相同:

transactions.Where(q => q.Products.Exists(x => unioned.Exists(z => z.ProductCode == x.ProductCode))).ToList();

答案 2 :(得分:0)

您可以执行以下操作:

List<Product> allproductsTrans = new List<Product>();
transactions.ForEach(p => allproductsTrans.Concat(p.Products));
var result = allproductsTrans.Intersect(unioned);

但正如 Slava Utesinov 在评论中所说,以下代码会做同样的事情:

transactions.SelectMany(x => x.Products).Intersect(unioned)

答案 3 :(得分:0)

您可以与ID相交,而不是使用EqualityComparer,然后根据需要按ID查找对象。

您的示例:

transactions.Where(q => q.Products.Select(x => x.ProductCode).Intersect(unioned.Select(x => x.ProductCode)).Any());

一般情况:

var ids = list1.Select(x => x.Id).Intersect(list2.Select(x => x.Id));
var result = list1.Where(x => ids.Contains(x.Id));