So führen Sie 2 List <T> zusammen und entfernen doppelte Werte in C #

158

Ich habe zwei Listen Liste, die ich in der dritten Liste kombinieren und doppelte Werte aus diesen Listen entfernen muss

Ein bisschen schwer zu erklären, also lassen Sie mich ein Beispiel zeigen, wie der Code aussieht und was ich als Ergebnis möchte. In einem Beispiel verwende ich den Int-Typ und nicht die ResultAnalysisFileSql-Klasse.

first_list = [1, 12, 12, 5]

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

Das Ergebnis der Kombination der beiden Listen sollte zu dieser Liste führen: result_list = [1, 12, 5, 7, 9]

Sie werden feststellen, dass das Ergebnis die erste Liste enthält, einschließlich der beiden "12" -Werte, und in second_list einen zusätzlichen Wert von 12, 1 und 5 enthält.

ResultAnalysisFileSql-Klasse

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


    }

Gibt es einen Beispielcode zum Kombinieren und Entfernen von Duplikaten?

Kiquenet
quelle

Antworten:

287

Haben Sie sich Enumerable.Union angesehen?

Diese Methode schließt Duplikate aus dem Rückgabesatz aus . Dies unterscheidet sich von der Concat-Methode, bei der alle Elemente in den Eingabesequenzen einschließlich Duplikaten zurückgegeben werden.

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

// ulist output : 1, 12, 5, 7, 9
Adriaan Stander
quelle
6
@Dr TJ: Implementiert Ihre Personenklasse IEqualityComparer <T>? In diesem Fall müssen Sie Ihre GetHashCode- und Equals-Methoden überprüfen. Siehe den Abschnitt "Anmerkungen" von msdn.microsoft.com/en-us/library/bb341731.aspx .
Tomas Narros
1
Es ist wichtig zu beachten, dass ich bei zwei verschiedenen Sammlungen auf Probleme gestoßen bin : "Sie können nicht zwei verschiedene Typen verbinden, es sei denn, einer erbt vom anderen" von stackoverflow.com/a/6884940/410937, was zu einem cannot be inferred from the usageFehler führte.
Atconway
30

warum nicht einfach zB

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

oh ... laut msdn kannst du das weglassen.Distinct()

Diese Methode schließt Duplikate aus dem Rückgabesatz aus

Andreas Niedermair
quelle
25

Union hat keine gute Leistung: In diesem Artikel wird beschrieben, wie man sie miteinander vergleicht

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

Listen und LINQ-Zusammenführung: 4820 ms
Wörterbuch-Zusammenführung: 16 ms
HashSet und IEqualityComparer: 20 ms
LINQ Union und IEqualityComparer: 24 ms

fateme maddahi
quelle
1
Ein weiterer Vorteil der Verwendung einer Wörterbuchzusammenführung -> Ich habe zwei Listen, die aus DB-Daten stammen. Und meine Daten haben ein Zeitstempelfeld, das sich in den beiden Datenlisten unterscheidet. Mit der Union bekomme ich Duplikate, weil der Zeitstempel anders ist. Aber mit der Zusammenführung kann ich entscheiden, welches eindeutige Feld ich im Wörterbuch berücksichtigen möchte. +1
JimSan
Kann je nach Prozessorgeschwindigkeit variieren, hängt davon ab, welche Art von CPU Sie haben.
Asad Ali
7
Und am Ende des Artikels heißt es: "Ich bevorzuge LINQ Union, weil es die Absicht sehr klar kommuniziert." ;) (auch gab es nur einen Unterschied von 8 ms)
James Wilkins
1
Bei kleinen Listen, bei denen der Unterschied vernachlässigbar ist, Unionführt dies zu sauberem und besser lesbarem Code. Wenn Sie Zeit für die Hyperoptimierung von Code aufwenden, wenn dieser nicht langsam ist, kann dies später zu Wartungsarbeiten führen.
Elolos
14

Verwenden Sie Linqs Union:

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();
Robert Jeppesen
quelle
11
    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);
Faizan S.
quelle