2015-09-02 5 views
0

Я хочу, чтобы объединить два списка следующего классаКак объединить два списка

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

Теперь у меня есть 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}); 

То, что я хотел бы иметь, когда я объединить эти 2 перечислены является следующий результат

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

в первом списке свойство CountBehaviorInterview всегда будет 0, а на с ecand list CountContacts всегда будет 0.

Я пробовал использовать союз, но все, что он делает, возвращает список с 2 списками внутри. Есть ли способ объединить их так, как мне нужно?

+0

У вас есть две проблемы с вашим класса 'ContactsByUser', кстати. Во-первых, ваш метод Equals будет сбой, если ваш тип будет сопоставлен с чем-то, что не передается в 'ContactsByUser'. Во-вторых, вы никогда не должны ** вычислять 'GetHashCode' в поле/свойство, которое изменено. Значение 'GetHashCode' ** не должно ** изменяться на время жизни объекта, чтобы оно работало в любой хэш-структуре, например' Dictionary <,>'. – Enigmativity

ответ

0

Если вы хорошо с изменением объектов в contacts списке, вы можете использовать простой Join с foreach:

foreach(var joined in contacts.Join(interviews, 
            o => o.UserId, 
            i => i.UserId, 
            (originalContact, i) => new {originalContact, i.CountBehaviorInterview})) 
{ 
    joined.originalContact.CountBehaviorInterview = joined.CountBehaviorInterview; 
} 

Если вы хотите создать новые экземпляры ContactsByUser, тогда вы re look for левое внешнее соединение, что-то вроде этого:

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

или, используя другой метод (может быть медленнее, в зависимости от ваших данных, но, вероятно, не имеет значения):

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

Если вы не хотите, чтобы создать новый экземпляр 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; 
}); 
0

Вот как я бы решить это:

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

Это хорошо ручки отсутствуют, а также дублировать элементы в interviews списке.

Я получаю этот результат:

result

Смежные вопросы