2016-01-14 4 views
2

У меня есть список класса транзакций:Intersect список список объектов и список объектов

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(); 

И я хочу Пересечение объединенных и транзакционных продуктов, Этот код не работает:

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

Я думаю, причина в том, что транзакционная длина продукта является вариантом и длина соединения фиксирована.

Как я могу это сделать?

+0

Если я правильно понял, вы хотите взять все продукты из всех транзакций, а затем этот список пересечется с 'unione d', правильно? – libik

+0

В чем проблема? – Mukund

+0

Да, и список объединений имеет список продуктов, только два продукта в каждом списке, но транзакционные продукты имеют переменную длину. – danialtehrani

ответ

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()); 
} 
+0

Спасибо stuard – danialtehrani

+0

@danialtehrani не проблема :) – stuartd

0

Попробуйте это решение witho используя Intersect. Я использую ProductCode, чтобы проверить, если Product одно и то же:

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

Он возвращает транзакции, которые имеют один или несколько продуктов для объединения. Я хочу, чтобы транзакции имели все продукты union. Спасибо – danialtehrani

+0

Позвольте мне понять. Что вы хотите - это транзакции, которые имеют в продуктах все элементы в объединении? Итак, вы имеете в виду, что t.Products = unioned (это не код)? – erikscandola

+0

да, я хочу, чтобы все транзакции имели все продукты union. – danialtehrani

0

Вы могли бы сделать что-то вроде:

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

но Слава Utesinov сказал в комментариях, следующий код будет делать то же самое :

transactions.SelectMany(x => x.Products).Intersect(unioned) 
Смежные вопросы