我有一个交易类列表:
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());
我认为原因是交易产品长度是变化的,并且联合长度是固定的。
我该怎么做?
答案 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));