Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > LINQ (Language-Integrated Query) > Linq запрос к двум List<T>


Автор: TheRam 6.2.2014, 16:15
Здравствуйте форумчане.

Вот начал изучать linq и придумал себе задачу, для практики и в ней же застрял:

Есть класс Product с полями ID и Money

Есть два List<Product> list1, list2

Как с помощью linq to object получить набор данных вида ID,list1.Money, list2.Money из list1 и list2 у которых ID равны, но различаются по полю Money и list1.ID нет в list2 (list2.Money в данном случае установить в 0)?

Первую часть с одинаковыми ID, но разными суммами я сделал, а вот как сделать выборку данных, которых нет в list2 с той же проекцией, как и в первой части, что бы их объединить - не получается.


Автор: Certain 6.2.2014, 18:27
Если я правильно понял Вас
Код

class Product
{
    public int id;
    public decimal money;
}
void Main()
{
    List<Product> list1 = new List<Product> {new Product() { id = 1, money = 10.0m},
                                             new Product() { id = 2, money = 20.0m},
                                             new Product() { id = 3, money = 30.0m},
                                             new Product() { id = 4, money = 40.0m},
                                             new Product() { id = 5, money = 50.0m}};
    List<Product> list2 = new List<Product> {new Product() { id = 1, money = 11.0m},
                                             new Product() { id = 2, money = 21.0m},
                                             new Product() { id = 3, money = 30.0m},
                                             new Product() { id = 4, money = 40.0m}};
                                             
    var result = list1.Where (l => list2.Any (li => li.id == l.id && li.money != l.money) 
                              || !list2.Any (li => li.id == l.id))
                      .Select (l => new {Id     = l.id, 
                                         Money1 = l.money, 
                                         Money2 = list2.Where (li => li.id == l.id)
                                                       .DefaultIfEmpty(new Product())
                                                       .FirstOrDefault ().money});    
        result.Dump();
}



Автор: TheRam 7.2.2014, 08:45
Спасибо большое, думал не в том направлении, шел по пути объединения трех под запросов.

Но есть еще один вопрос: в оригинале у меня вместо int ID у меня long ID и после выполнения запроса, у меня выводится правильные результаты (9 шт) и еще 128 каких-то данных, с ID = -2147483648 у всех 128 элементов. Вопрос: что это такое и почему их получается 128, когда элементов для сравнения в каждом list > 10 000?
 


Автор: Certain 7.2.2014, 09:17
Думаю Вам лучше сюда исходник скинуть...
Проблема может быть
1. В самом списке.
2. В классе Product.
3. В коде, который находится после инициализации списков и до вызова linq запроса.

ID = -2147483648... диапазон типа System.Int32 от -2147483648 до 2147483647  smile 

Автор: TheRam 7.2.2014, 11:14
Спасибо большое, напоминание диапазона int32 навело на мысль о потери данных при преобразовании типов, что и было. Сначала поле ID у меня  было int, а после обноружил, что нужен long, в результате в одном месте получилось преобразование из long в int, а потом обратно в long smile Теперь все работает как надо smile

А можно еще вопросик: а при использовании list1.Except(list2) можно задать похожую проекцию, как в случае первого варианта?

Автор: Certain 7.2.2014, 12:19
Да, можно, но придётся писать компаратор:
Код

class Product : IEqualityComparer<Product>
        {
            public int id;
            public decimal money;

            public bool Equals(Product p1, Product p2)
            {
                if (Object.ReferenceEquals(p1, p2)) return true;

                if (Object.ReferenceEquals(p1, null) || Object.ReferenceEquals(p2, null))
                    return false;
                return p1.id == p2.id && p1.money == p2.money;
            }

            public int GetHashCode(Product p)
            {
                if (Object.ReferenceEquals(p, null)) return 0;

                int hashProductMoney = p.money.GetHashCode();

                int hashProductId = p.id.GetHashCode();

                return hashProductMoney ^ hashProductId;
            }
        }


и сам запрос:
Код

var result = list1.Except(list2, new Product()).Select (l => new {Id     = l.id, 
                                                                  Money1 = l.money, 
                                                                  Money2 = list2.Where (li => li.id == l.id)
                                                                                .DefaultIfEmpty(new Product())
                                                                                .FirstOrDefault ().money});

Автор: TheRam 7.2.2014, 13:23
Спасибо большое!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)