C# 使用 Linq 比较列表并获取值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1193345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 10:30:05  来源:igfitidea点击:

Compare lists and get values with Linq

c#.netlinq

提问by Kris-I

My object is "MyClass" with 2 properties : Id (int) and HourBy (int)

我的对象是具有 2 个属性的“MyClass”:Id (int) 和 HourBy (int)

I have two list :

我有两个列表:

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

I'd like to get one list with : - Object from List1 present in List2 based on Id with Hourby (list2) < Hourby in List1 - Object from List1 no present in List2

我想获得一个列表: - List2 中存在的 List1 中的对象,基于 Id with Hourby (list2) < Hourby in List1 - List1 中的对象不存在于 List2 中

//#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);

Thanks,

谢谢,

采纳答案by Kris-I

I use this code, it's not perfect but working and may be clearer for newbie in Linq (like me)

我使用此代码,它并不完美但有效,对于 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);
        }            
    }   
}

Thanks for you help,

谢谢你的帮助,

回答by Oliver Hanappi

You can do this by the following Linq statement:

您可以通过以下 Linq 语句执行此操作:

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

Best Regards

此致

回答by Kirschstein

I think this is what you're after, based on the example lists you supplied...

根据您提供的示例列表,我认为这就是您所追求的......

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

回答by Lloyd

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

回答by bruno conde

Here's a solution:

这是一个解决方案:

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

回答by MattH

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