Сравните списки и получите значения с Linq

2

Мой объект - это MyClass с двумя свойствами: Id (int) и HourBy (int)

У меня есть два списка:

var List1 = new List<MyClass>();
var List2 = new List<MyClass>();

Я хотел бы получить один список: - Объект из списка 1, присутствующий в List2 на основе Id с Hourby (list2) < Час в списке1 - Объект из списка1 отсутствует в списке2

//#Sample1
//List1 :
List1.add(new MyClass(1,10));
List1.add(new MyClass(2,20));
List1.add(new MyClass(3,30));
//List2 :
List2.add(new MyClass(1,10)); 
List2.add(new MyClass(2,15));
//I'd like to get :
new MyClass(2,5);
new MyClass(3,30);

//Sample2
List1 :
List1.add(new MyClass(1,10));
List1.add(new MyClass(2,20));
List1.add(new MyClass(3,30));
//List2 :
List2.add(new MyClass(1,10)); 
List2.add(new MyClass(2,15));
List2.add(new MyClass(2,2));
//I'd like to get :
new MyClass(2,3);
new MyClass(3,30);

Спасибо,

  • 0
    Можете ли вы подтвердить, что это именно то, что вы хотите ..... Вы хотите вернуть все элементы в list1, которые присутствуют в list2, но имеют более низкое значение свойства HourBy в List2, и все элементы, которые присутствуют в List2, но отсутствуют в List1?
  • 0
    Я согласен, прозаическое объяснение не очень понятно, но примеры показывают более четко требование. Мне интересно видеть разные подходы, которые люди использовали в своих ответах (хотя они не все функционально эквивалентны)
Показать ещё 3 комментария
Теги:
linq

6 ответов

1
Лучший ответ

Я использую этот код, он не идеален, но работает и может быть яснее для новичков в Linq (например, я)

List< MyClass> listRes = new List< MyClass>();
foreach ( MyClass item in list1)
{
    var exist = list2
        .Select(x => x.MyClass)
        .Contains(item);

    if (!exist)
        listRes.Add(item);
    else
    {
        var totalFromOther = list2
            .Where(x => x.MyClass.Id == item.Id)
            .Sum(y => y.HourBy);

        if (item.HourBy != totalFromOther)
        {        
            item.HourBy = item.HourBy - totalFromOther;
            listRes.Add(item);
        }            
    }   
}

Спасибо за помощь,

4

Вы можете сделать это с помощью следующего оператора Linq:

var result = List1.Where(x => !List2.Select(y => y.Id).Contains(x.Id)
    || List2.Single(y => x.Id == y.Id).HourBy < x.HourBy);

С наилучшими пожеланиями

  • 0
    Привет, Оливер, я создал свой linq-запрос в своем проекте в соответствии с твоим примером. Он мне помог. Спасибо
1

Здесь решение:

        var qry = from ee in
                       (from e1 in list1
                        join e2 in list2 on e1.Id equals e2.Id into gj
                        from e in gj.DefaultIfEmpty()
                        select new { 
                            e1.Id,
                            MainHourBy = e1.HourBy,
                            SecondHourBy = (e == null ? 0 : e.HourBy)
                        })
                   where ee.SecondHourBy < ee.MainHourBy
                   group ee by ee.Id into g
                   select new MyClass
                   {
                       Id = g.Key,
                       HourBy = g.First().MainHourBy - g.Sum(el => el.SecondHourBy)
                   };
1

Я думаю, что это то, что вам нужно, на основе приведенных списков примеров...

var list3 = new List<MyClass>();

foreach(var item in list1)
{
   var totalFromOther = list2.Where(x => x.id == item.id).Sum(y => y.HourBy);
   var newItem = new MyClass() { id = item.Id, HourBy = item.HourBy - totalFromOther };
   if(newItem.HourBy > 0)
     list3.Add(newItem);
}
0
//Group list 2, so there is one entry per ID, with HourBy = total hour by
var summedL2 = from item2 in List2
              group item2 by item2.ID into g
              select new Test(g.Key, g.Sum(item => item.HourBy));

var result = 
            //Select items from list1
             from item1 in List1
             //Left join to our summed List2
             join item2s in summedL2 on item1.ID equals item2s.ID into tempItem2s
             from item2 in tempItem2s.DefaultIfEmpty()
             //Where there is no match, or item2 is < item1
             where (item2 == null || item2.HourBy < item1.HourBy)
             //Select a new Test object, with the HourBy changed
             select new Test(item1.ID, item1.HourBy - (item2 == null ? 0 : item2.HourBy));
0
var agg1 = from l in list1
           group l by l.ID into g
           select new { g.Key, Sum = g.Sum(_ => _.HourBy) };
var agg2 = from l in list2
           group l by l.ID into g
           select new { g.Key, Sum = g.Sum(_ => _.HourBy) };

var q = from l1 in agg1
        let l2 = agg2.FirstOrDefault(_ => _.Key == l1.Key)
        let sum = l1.Sum - (l2 != null ? l2.Sum : 0)
        where sum != 0
        select new MyClass(l1.Key, sum);

var list3 = q.ToList();
  • 0
    Я не слишком знаком с предложением 'let'. Оценивается ли он один раз для запроса или один раз для строки в этом случае?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню