合并多个自定义对象列表的内容-C#
我有一个类项目
public class Project
{ public int ProjectId { get; set; }
public string ProjectName { get; set; }
public string Customer { get; set; }
public string Address{ get; set; }
}
我有3个列表
List<Project> lst1; List<Project> lst2; List<Project> lst3;
lst1
包含具有ProjectId和ProjectName的 Person
对象.
lst1
contains Person
objects with ProjectId and ProjectName.
ProjectId = 1,ProjectName ="X",客户=空,地址=空
ProjectId = 2,ProjectName ="Y",客户=空,地址=空
lst2
包含具有ProjectId和Customer的 Person
对象
lst2
contains Person
objects with ProjectId and Customer
ProjectId = 1,ProjectName = null,客户="c1",地址= null
ProjectId = 2,ProjectName = null,客户="c2",地址= null
和
lst3
包含具有ProjectId和Address的 Person
对象
lst3
contains Person
objects with ProjectId and Address
ProjectId = 1,ProjectName = null,客户= null,地址="a1"
ProjectId = 2,ProjectName = null,客户= null,地址="a2"
.
考虑到每个列表中都有多个这样的记录,并且每个项目的ProjectId为Uniqe,我如何合并/合并这些列表以获取包含合并对象的一个列表
Considering there are multiple such records in each list and ProjectId is Uniqe for each project, How can I merge/combine these list to get one list with merged objects
ProjectId = 1,ProjectName ="X",Customer ="c1",地址="a1"
ProjectId = 2,ProjectName ="Y",Customer ="c2",地址="a2"
我发现这些链接很相似,并尝试使用它,但无法达到结果
I found thse links similar and tried with it but could not meet the results
谢谢.
可以很简单地通过多步骤方法来完成.首先,定义 Func< Project,Project,Project>
来处理实际的记录合并.也就是说,您正在定义一个具有与 public Project SomeMethod(Project p1,Project p2)
等效的签名的方法.此方法实现了您上面概述的合并逻辑.接下来,我们将列表的元素连接在一起,然后按 ProjectId
对其进行分组,使用合并委托作为 GroupBy
的重载中的聚合函数,该函数接受结果选择器:
This could be done in a multi-step approach pretty simply. First, define a Func<Project, Project, Project>
to handle the actual record merging. That is, you are defining a method with a signature equivalent to public Project SomeMethod(Project p1, Project p2)
. This method implements the merging logic you outlined above. Next, we concatenate the elements of the lists together before grouping them by ProjectId
, using our merge delegate as the an aggregate function in the overload of GroupBy
which accepts a result selector:
Func<Project, Project, Project> mergeFunc = (p1,p2) => new Project
{
ProjectId = p1.ProjectId,
ProjectName = p1.ProjectName == null ? p2.ProjectName : p1.ProjectName,
Customer = p1.Customer == null ? p2.Customer : p1.Customer,
Address = p1.Address == null ? p2.Address : p1.Address
};
var output = lst1.Concat(lst2).Concat(lst3)
.GroupBy(x => x.ProjectId, (k, g) => g.Aggregate(mergeFunc));
以下是对上述逻辑以及输出的快速而肮脏的测试:
Here's a quick and dirty test of the above logic along with output:
List<Project> lst1; List<Project> lst2; List<Project> lst3;
lst1 = new List<Project>
{
new Project { ProjectId = 1, ProjectName = "P1" },
new Project { ProjectId = 2, ProjectName = "P2" },
new Project { ProjectId = 3, ProjectName = "P3" }
};
lst2 = new List<Project>
{
new Project { ProjectId = 1, Customer = "Cust1"},
new Project { ProjectId = 2, Customer = "Cust2"},
new Project { ProjectId = 3, Customer = "Cust3"}
};
lst3 = new List<Project>
{
new Project { ProjectId = 1, Address = "Add1"},
new Project { ProjectId = 2, Address = "Add2"},
new Project { ProjectId = 3, Address = "Add3"}
};
Func<Project, Project, Project> mergeFunc = (p1,p2) => new Project
{
ProjectId = p1.ProjectId,
ProjectName = p1.ProjectName == null ? p2.ProjectName : p1.ProjectName,
Customer = p1.Customer == null ? p2.Customer : p1.Customer,
Address = p1.Address == null ? p2.Address : p1.Address
};
var output = lst1
.Concat(lst2)
.Concat(lst3)
.GroupBy(x => x.ProjectId, (k, g) => g.Aggregate(mergeFunc));
IEnumerable<bool> assertedCollection = output.Select((x, i) =>
x.ProjectId == (i + 1)
&& x.ProjectName == "P" + (i+1)
&& x.Customer == "Cust" + (i+1)
&& x.Address == "Add" + (i+1));
Debug.Assert(output.Count() == 3);
Debug.Assert(assertedCollection.All(x => x == true));
-输出---
IEnumerable<Project> (3 items)
ProjectId ProjectName Customer Address
1 P1 Cust1 Add1
2 P2 Cust2 Add2
3 P3 Cust3 Add3