Comment fusionner 2 List <T> et en supprimer les valeurs en double en C #

159

J'ai deux listes Liste que je dois combiner dans la troisième liste et supprimer les valeurs en double de ces listes

Un peu difficile à expliquer, alors laissez-moi vous montrer un exemple de ce à quoi ressemble le code et de ce que je veux en conséquence, dans l'exemple, j'utilise le type int et non la classe ResultAnalysisFileSql.

first_list = [1, 12, 12, 5]

deuxième_liste = [12, 5, 7, 9, 1]

Le résultat de la combinaison des deux listes doit aboutir à cette liste: résultant_list = [1, 12, 5, 7, 9]

Vous remarquerez que le résultat a la première liste, y compris ses deux valeurs "12", et dans second_list a une valeur supplémentaire de 12, 1 et 5.

Classe ResultAnalysisFileSql

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


    }

Un exemple de code pour combiner et supprimer les doublons?

Kiquenet
la source

Réponses:

288

Avez-vous jeté un œil à Enumerable.Union

Cette méthode exclut les doublons de l'ensemble de retour . Il s'agit d'un comportement différent de la méthode Concat, qui renvoie tous les éléments des séquences d'entrée, y compris les doublons.

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
la source
6
@Dr TJ: Est-ce que votre classe personne implémente IEqualityComparer <T>? Si tel est le cas, vous devrez vérifier vos méthodes GetHashCode et Equals. Consultez la section Remarques de msdn.microsoft.com/en-us/library/bb341731.aspx .
Tomas Narros
1
Important à noter car j'ai rencontré des problèmes en utilisant ceci sur 2 collections différentes: "Vous ne pouvez pas unir deux types différents, à moins que l'un n'hérite de l'autre" de stackoverflow.com/a/6884940/410937 qui a généré une cannot be inferred from the usageerreur.
atconway
30

pourquoi pas simplement par exemple

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

oh ... selon msdn, vous pouvez laisser de côté le.Distinct()

Cette méthode exclut les doublons de l'ensemble de retour

Andreas Niedermair
la source
25

Union n'a pas de bonnes performances: cet article décrit comment les comparer ensemble

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

Listes et fusion LINQ: 4820 ms Fusion de
dictionnaire: 16
ms HashSet et IEqualityComparer: 20ms
LINQ Union et IEqualityComparer: 24ms

fateme maddahi
la source
1
Aussi un autre avantage de l'utilisation d'une fusion de dictionnaire -> J'ai deux listes provenant de données de base de données. Et mes données ont un champ d'horodatage, qui est différent dans les deux listes de données. Avec le syndicat, j'obtiens des doublons en raison de l'horodatage différent. Mais avec la fusion, je peux décider quel champ unique je veux considérer dans le dictionnaire. +1
JimSan
Peut varier en fonction de la vitesse du processeur, dépend du type de processeur dont vous disposez.
Asad Ali
7
Et à la fin de l'article, il est dit: "Je préfère LINQ Union car il communique très clairement l'intention." ;) (aussi, il n'y avait qu'une différence de 8 ms)
James Wilkins
1
Pour les petites listes où la différence est négligeable, il en Unionrésulte un code plus propre et plus lisible. Passer du temps à hyper-optimiser le code lorsqu'il n'est pas lent peut entraîner une pénalité de maintenance sur la route.
elolos
14

Utilisez l'Union de Linq:

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
la source
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.
la source