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
Compare lists and get values with Linq
提问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));