如何根据属性合并两个列表
本文关键字:两个 列表 何根 属性 合并 | 更新日期: 2023-09-27 18:11:03
我有两个列表,一个是假的,一个是真的,比如:
前// fake (list 1)
{ ID = 1, Year = 2011, X = "" }
, { ID = 2, Year = 2012, X = "" }
, { ID = 3, Year = 2013, X = "" }
// real (list 2)
{ ID = 35, Year = 2011, X = "Information" }
, { ID = 77, Year = 2013, X = "Important" }
我想合并它们寻找年份,结果应该是:
后{ ID = 35, Year = 2011, X = "Information" }
, { ID = 2, Year = 2012, X = "" }
, { ID = 77, Year = 2013, X = "Important" }
它必须删除第一个列表中具有相同年份的元素,并将第二个列表中具有相同年份的元素添加到第一个列表中,保持顺序。
如何使用Linq?
您应该能够使用"left join":
from f in fake
join r in real
on f.Year equals r.Year
into joinResult
from r in joinResult.DefaultIfEmpty()
select new
{
ID = r == null ? f.ID : r.ID,
Year = f.Year,
X = r == null ? f.X : r.X
};
Justin的查询是最有效的方法,但是如果您关心保持相同的对象(并且不从查询中创建新记录),您可以这样做:
var combined = from f in fake
let r = (from r1 in real
where r1.Year == f.Year
select r1).SingleOrDefault()
select r ?? f;
Using IEnumerable。联合和等价比较器。
注:如果真实列表有更多的元素(假列表中没有出现的年份),那么与左连接相比,这将导致不同的结果。左连接不会返回那些可能是期望结果的结果(没有从OP中清除)。
public class MyClass
{
public int ID {get; set;}
public int Year {get; set;}
public string X {get; set;}
}
public class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
public bool Equals(MyClass x, MyClass y)
{
return x.Year == y.Year;
}
public int GetHashCode(MyClass obj)
{
return obj.ToString().ToLower().GetHashCode();
}
}
void Main()
{
var fake = new List<MyClass> {
new MyClass { ID = 1, Year = 2011, X = "" }
, new MyClass { ID = 2, Year = 2012, X = "" }
, new MyClass { ID = 3, Year = 2013, X = "" }
};
var real = new List<MyClass> {
new MyClass { ID = 35, Year = 2011, X = "Information" }
, new MyClass { ID = 77, Year = 2013, X = "Important" }
};
var merged = real.Union(fake, new MyClassEqualityComparer());
}
与其自己定义假列表,不如让Linq帮你定义:
Enumerable.Range(2011,3) //2011, 2012, 2013
//use the overload that provides a 0-based ordinal position of each element
.Select(x,i=> new {ID = i+1, Year = x, X = String.Empty)
//now you have your fake list; join with the "real" list based on Year fields,
//taking the real element wherever it exists and the fake one otherwise
.Join(real, l=>l.Year, r=>r.Year, (l,r) => r == null ? l : r);
这将产生您想要的结果集。但是,您可能需要为列表项定义一个命名类型,因为即使两个单独定义的匿名类型具有相同的成员类型/名称,也不能隐式转换。