2010-10-27 15 views
107

devo List due liste che ho bisogno di combinare e rimuovere i valori duplicati di entrambe le listecome unire 2 Elenco <T> con la rimozione di valori duplicati in C#

un po 'difficile da spiegare, quindi mi permetta di mostrare un esempio di ciò che il codice sembra, e quello che voglio come risultato, in esempio io uso il tipo int non ResultAnalysisFileSql class.

first_list = [1, 12, 12, 5]

second_list = [12, 5, 7, 9, 1]

Il risultato della combinazione delle due liste dovrebbe tradursi in questa lista: result_list = [1, 12, 5, 7, 9]

Noterai che il risultato ha il primo elenco, inclusi i suoi due valori "12", e in second_list ha un valore aggiuntivo di 12, 1 e 5.

classe ResultAnalysisFileSql codice

[Serializable] 
    public partial class ResultAnalysisFileSql 
    { 
     public string FileSql { get; set; } 

     public string PathFileSql { get; set; } 

     public List<ErrorAnalysisSql> Errors { get; set; } 

     public List<WarningAnalysisSql> Warnings{ get; set; } 

     public ResultAnalysisFileSql() 
     { 

     } 

     public ResultAnalysisFileSql(string fileSql) 
     { 
      if (string.IsNullOrEmpty(fileSql) 
       || fileSql.Trim().Length == 0) 
      { 
       throw new ArgumentNullException("fileSql", "fileSql is null"); 
      } 

      if (!fileSql.EndsWith(Utility.ExtensionFicherosErrorYWarning)) 
      { 
       throw new ArgumentOutOfRangeException("fileSql", "Ruta de fichero Sql no tiene extensión " + Utility.ExtensionFicherosErrorYWarning); 
      } 

      PathFileSql = fileSql; 
      FileSql = ObtenerNombreFicheroSql(fileSql); 
      Errors = new List<ErrorAnalysisSql>(); 
      Warnings= new List<WarningAnalysisSql>(); 
     } 

     private string ObtenerNombreFicheroSql(string fileSql) 
     { 
      var f = Path.GetFileName(fileSql); 
      return f.Substring(0, f.IndexOf(Utility.ExtensionFicherosErrorYWarning)); 
     } 


     public override bool Equals(object obj) 
     { 
      if (obj == null) 
       return false; 
      if (!(obj is ResultAnalysisFileSql)) 
       return false; 

      var t = obj as ResultAnalysisFileSql; 
      return t.FileSql== this.FileSql 
       && t.PathFileSql == this.PathFileSql 
       && t.Errors.Count == this.Errors.Count 
       && t.Warnings.Count == this.Warnings.Count; 
     } 


    } 

Qualsiasi campione per combinare e rimuovere i duplicati?

risposta

203

Hai avuto uno sguardo al Enumerable.Union

Questo metodo esclude i duplicati dal rientro impostare. Questo è diverso comportamento al metodo Concat , che restituisce tutti gli elementi nelle sequenze di ingresso comprese duplicati.

List<int> list1 = new List<int> { 1, 12, 12, 5}; 
List<int> list2 = new List<int> { 12, 5, 7, 9, 1 }; 
List<int> ulist = list1.Union(list2).ToList(); 
+1

quando uso 'Collezione ' non funziona e passa solo tutti gli elementi ... –

+5

@Dr TJ: la tua classe implementa IEqualityComparer ? In tal caso, dovrai verificare i tuoi metodi GetHashCode ed Equals. Vedere la sezione Note di http://msdn.microsoft.com/en-us/library/bb341731.aspx. –

+1

Importante da notare perché ho riscontrato problemi utilizzando questo in 2 raccolte diverse: "Non puoi unire due tipi diversi, a meno che uno non erediti dall'altro" da http://stackoverflow.com/a/6884940/410937 che ha prodotto un 'non può essere dedotto dall'errore di utilizzo '. – atconway

22

perché non semplicemente ad esempio

var newList = list1.Union(list2)/*.Distinct()*//*.ToList()*/; 

oh ... secondo msdn si può tralasciare il .Distinct()

Questo metodo esclude i duplicati dal il ritorno impostato

12

di utilizzare LINQ dell'Unione:

using System.Linq; 
var l1 = new List<int>() { 1,2,3,4,5 }; 
var l2 = new List<int>() { 3,5,6,7,8 }; 
var l3 = l1.Union(l2).ToList(); 
10
List<int> first_list = new List<int>() { 
     1, 
     12, 
     12, 
     5 
    }; 

    List<int> second_list = new List<int>() { 
     12, 
     5, 
     7, 
     9, 
     1 
    }; 

    var result = first_list.Union(second_list); 
+1

Non è necessario chiamare Distinct, leggere la documentazione http://msdn.microsoft.com/en-us/library/bb341731.aspx, o provarlo da soli ... –

16

Unione non ha buone prestazioni: questo article descrivere confrontarle con insieme

var dict = list2.ToDictionary(p => p.Number); 
foreach (var person in list1) 
{ 
     dict[person.Number] = person; 
} 
var merged = dict.Values.ToList(); 

liste e LINQ merge: 4820ms
Dizionario unione: 16ms
HashSet e IEqualityComparer: 20ms
LINQ Union e IEqualityComparer: 24ms

+0

Anche un altro vantaggio dell'utilizzo di un'unione di dizionari - > Ho due liste in arrivo dai dati DB. E i miei dati hanno un campo data/ora, che è diverso nei due elenchi di dati. Con il sindacato ottengo duplicati a causa del timestamp che è diverso. Ma con l'unione posso decidere quale campo unico voglio considerare nel dizionario. +1 – JimSan

+0

Può variare a seconda della velocità del processore, dipende dal tipo di CPU in uso. –

+2

E alla fine dell'articolo dice "Preferisco LINQ Union perché comunica molto chiaramente l'intento." ;) (anche, c'era solo una differenza di 8 ms) –

Problemi correlati