[英]How to Merge two lists
I want to merge two list of the following class 我想合并以下课程的两个列表
public class ContactsByUser
{
public int UserId { get; set; }
public string Username { get; set; }
public int CountContacts { get; set; }
public int CountBehaviorInterview { get; set; }
public override bool Equals(object obj)
{
return this.UserId == ((ContactsByUser)obj).UserId;
}
public override int GetHashCode()
{
return UserId.GetHashCode();
}
}
Now I have 2 lists containing the following 现在我有2个包含以下内容的列表
List<ContactsByUser> contacts = new List<ContactsByUser>();
contacts.Add( new ContactsByUser { UserId = 1, Username = user1, CountContacts = 42, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 2, Username = user2, CountContacts = 25, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 3, Username = user3, CountContacts = 7, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 4, Username = user4, CountContacts = 10, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 5, Username = user5, CountContacts = 23, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 6, Username = user6, CountContacts = 60, CountBehaviorInterview = 0});
contacts.Add( new ContactsByUser { UserId = 7, Username = user7, CountContacts = 3, CountBehaviorInterview = 0});
List<ContactsByUser> interviews = new List<ContactsByUser>();
interviews .Add( new ContactsByUser { UserId = 1, Username = user1, CountContacts = 0, CountBehaviorInterview = 33});
interviews .Add( new ContactsByUser { UserId = 2, Username = user2, CountContacts = 0, CountBehaviorInterview = 21});
interviews .Add( new ContactsByUser { UserId = 3, Username = user3, CountContacts = 0, CountBehaviorInterview = 8});
interviews .Add( new ContactsByUser { UserId = 4, Username = user4, CountContacts = 0, CountBehaviorInterview = 17});
What I would like to have when I merge these 2 lists is the following result 当我合并这两个列表时,我想要的是以下结果
{ UserId = 1, Username = user1, CountContacts = 42, CountBehaviorInterview = 33});
{ UserId = 2, Username = user2, CountContacts = 25, CountBehaviorInterview = 21});
{ UserId = 3, Username = user3, CountContacts = 7, CountBehaviorInterview = 8});
{ UserId = 4, Username = user4, CountContacts = 10, CountBehaviorInterview = 17});
{ UserId = 5, Username = user5, CountContacts = 23, CountBehaviorInterview = 0});
{ UserId = 6, Username = user6, CountContacts = 60, CountBehaviorInterview = 0});
{ UserId = 7, Username = user7, CountContacts = 3, CountBehaviorInterview = 0});
On the first list, the CountBehaviorInterview property will always be 0, and on the second list the CountContacts will always be 0. 在第一个列表上,CountBehaviorInterview属性将始终为0,在第二个列表上,CountContacts将始终为0。
I have tried using union but all it does is return a list with the 2 lists inside. 我试过使用union,但是它所做的只是返回一个带有2个列表的列表。 Is there a way merge these the way i need?
有没有一种方法可以将这些合并为我需要的方法?
If you're fine with changing the objects in the contacts
list, you could use a simple Join
with foreach
: 如果您可以更改
contacts
列表中的对象,可以使用带有foreach
的简单Join
:
foreach(var joined in contacts.Join(interviews,
o => o.UserId,
i => i.UserId,
(originalContact, i) => new {originalContact, i.CountBehaviorInterview}))
{
joined.originalContact.CountBehaviorInterview = joined.CountBehaviorInterview;
}
If you want to create new instances of ContactsByUser
, then you're looking for a left outer join, something like this: 如果要创建
ContactsByUser
新实例,那么您正在寻找左外部联接,如下所示:
var result = from i in contacts
join o in interviews on i.UserId equals o.UserId into j
from o in j.DefaultIfEmpty()
select new ContactsByUser
{
UserId = i.UserId,
Username = i.Username,
CountContacts = i.CountContacts,
CountBehaviorInterview = j.Any() ? j.Single().CountBehaviorInterview : 0
};
or, using a different method (may be slower, depending on your data, but probably doesn't matter): 或者,使用其他方法(可能会更慢,具体取决于您的数据,但可能无关紧要):
var result = from i in contacts
from o in interviews.Where(k => k.UserId == i.UserId).DefaultIfEmpty()
select new ContactsByUser
{
UserId = i.UserId,
Username = i.Username,
CountContacts = i.CountContacts,
CountBehaviorInterview = o != null ? o.CountBehaviorInterview : 0
};
If you don't want to create a new instance of ContactsByUser you could: 如果您不想创建ContactsByUser的新实例,则可以:
var interviewsByUserId = interviews.ToDictionary(i=>i.UserId, i=>i);
contacts.ForEach(c =>
{
ContactsByUser interview;
if (!interviewsByUserId.TryGetValue(c.UserId, out interview))
return;
c.CountBehaviorInterview = interview.CountBehaviorInterview;
});
Here's how I would tackle this: 这是我要解决的方法:
var lookup = interviews.ToLookup(i => i.UserId, i => i.CountBehaviorInterview);
var result =
contacts
.Select(c => new ContactsByUser()
{
UserId = c.UserId,
Username = c.Username,
CountContacts = c.CountContacts,
CountBehaviorInterview = lookup[c.UserId].Sum(),
})
.ToList();
This nicely handles missing and also duplicate items in the interviews
list. 这样可以很好地处理
interviews
列表中的缺失和重复项。
I get this result: 我得到这个结果:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.