2016-09-15 123 views
2
public class Contact 
    { 
     public string Name { get; set; } 
     public string Fax { get; set; } 
     public string Email {get; set; } 
    } 

,如果我有一個聯繫人列表,看起來像下面這樣:C#集合結合項目

List<Contact> contactList = 
╔═════╦══════╦═════════════╗ 
║Name ║ Fax ║ Email  ║ 
╠═════╬══════╬═════════════╣ 
║ a ║ 1 ║    ║ 
║ b ║  ║ [email protected] ║ 
║ c ║ 3 ║ [email protected] ║ 
║ a ║  ║ [email protected] ║   
║ b ║ 2 ║    ║ 
╚═════╩══════╩═════════════╝ 

我怎麼能結合的條目名稱相同,併產生這樣的結果?

╔═════╦══════╦═════════════╗ 
║Name ║ Fax ║ Email  ║ 
╠═════╬══════╬═════════════╣ 
║ a ║ 1 ║ [email protected] ║ 
║ b ║ 2 ║ [email protected] ║ 
║ c ║ 3 ║ [email protected] ║ 
╚═════╩══════╩═════════════╝ 

這是我試過到目前爲止:

var result = contactList.Select(contact => contact.Name) 
          .Distinct() 
          .Select(name => contactList.First(contact => contact.Name == name)) 
          .ToList(); 


foreach (var contact in contactList) 
      { 
       var c = result.First(r => r.Name == contact.Name); 
       c.Name = string.IsNullOrWhiteSpace(contact.Name) ? c.Name : contact.Name; 
       c.Fax = string.IsNullOrWhiteSpace(contact.Fax ? c.Fax : contact.Fax; 
       c.Email = string.IsNullOrWhiteSpace(contact.Email) ? c.Email : contact.Email; 
      } 

有沒有更有效的方法?

+3

什麼是您的重複定義?你期望的結果是什麼? –

+0

你問如何結合像項目?什麼構成「重複」,因爲根據我的定義,沒有重複。 – leigero

+0

在建立'List '時,添加額外的信息可能會更有效。 –

回答

4

看起來你需要做一個GroupBy然後我假設這些值是空值,所以你只是想獲得第一個非空值。

var results = (from contact in constactList 
       group contact by contact.Name into contacts 
       select new Contact 
       { 
        Name = contacts.Key, 
        Fax = contacts.FirstOrDefault(c => c.Fax != null)?.Fax, 
        Email = contacts.FirstOrDefault(c => c.Email != null)?.Email 
       }).ToList(); 

還是在方法的語法

var results = constactList.GroupBy(contact => contact.Name) 
    .Select(contacts => new Contact 
    { 
     Name = contacts.Key, 
     Fax = contacts.FirstOrDefault(c => c.Fax != null)?.Fax, 
     Email = contacts.FirstOrDefault(c => c.Email != null)?.Email 
    }).ToList(); 

或者,如果他們是空字符串,你也可以做

Fax = contacts.FirstOrDefault(c => !string.IsNullOrWhiteSpace(c.Fax))?.Fax 

如果你沒有C#6,然後下面

Fax = contacts.Where(c => !string.IsNullOrWhiteSpace(c.Fax)).Select(c => c.Fax).FirstOrDefault() 
+0

謝謝。你的解決方案非常清晰徹底。 – user941749

1

您可以使用字典。遍歷列表獲取缺失信息和過濾重複:

var dict = new Dictionary<string, Contact>(); 
foreach (var contact in contactList) 
{ 
    Contact existingContact; 
    if (dict.TryGetValue(contact.Name, out existingContact)) 
    { 
     if (String.IsNullOrEmpty(existingContact.Fax)) 
      existingContact.Fax = contact.Fax; 
     if (String.IsNullOrEmpty(existingContact.Email)) 
      existingContact.Email = contact.Email; 
    } 
    else 
    { 
     dict.Add(contact.Name, contact); 
    } 
} 
var list = dict.Values.ToList(); 

複雜性這種方法的是O(n)。此外,它需要O(n)額外的內存。

0

您應該認爲可能有沒有電子郵件或傳真的條目。

var contactList = new List<Contact> { 
    new Contact { Name="a", Fax = "1", Email=""}, 
    new Contact { Name="b", Fax = "", Email="[email protected]"}, 
    new Contact { Name="c", Fax = "3", Email="[email protected]"}, 
    new Contact { Name="a", Fax = "", Email="[email protected]"}, 
    new Contact { Name="b", Fax = "2", Email=""}, 

}; 

var result = (from c in contactList 
       .Where(contact => !string.IsNullOrEmpty(contact.Name)) 
       .Select(c => c.Name) 
       .Distinct() 
      let fax = contactList.FirstOrDefault(contact => contact.Name == c && 
        !string.IsNullOrEmpty(contact.Fax)) 
      let email = contactList.FirstOrDefault(contact => contact.Name == c && 
        !string.IsNullOrEmpty(contact.Email)) 
      select new Contact { 
       Name = c, 
       Fax = fax == null ? "" : fax.Fax, 
       Email = email == null ? "" : email.Email 
      }) 
      .ToList();