210 votes

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

J'ai deux listes que je dois combiner dans une troisième liste et supprimer les valeurs en double de cette liste.

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

première_liste = [1, 12, 12, 5]

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

Le résultat de la combinaison des deux listes devrait donner cette liste : liste_résultante = [1, 12, 5, 7, 9]

Vous remarquerez que le résultat contient la première liste, y compris ses deux valeurs "12", et que la deuxième liste contient 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 ?

399voto

astander Points 83138

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

Cette méthode exclut les doublons de l'ensemble des retours. . Ce comportement est différent du comportement de la méthode Concat qui retourne tous les éléments dans les séquences d'entrée, y compris les 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

8 votes

@Dr TJ : Votre classe de personne implémente-t-elle IEqualityComparer<T> ? Si oui, vous devrez vérifier vos méthodes GetHashCode et Equals. Voir la section Remarques de msdn.microsoft.com/fr/us/library/bb341731.aspx .

1 votes

Important à noter car j'ai rencontré des problèmes en l'utilisant sur 2 collections différentes : "Vous ne pouvez pas réunir deux types différents, sauf si l'un hérite de l'autre" de stackoverflow.com/a/6884940/410937 qui a donné un cannot be inferred from the usage erreur.

38voto

Andreas Niedermair Points 8907

Pourquoi ne pas simplement eg

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

oh ... selon la documentation vous pouvez laisser de côté le .Distinct()

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

33voto

fateme maddahi Points 401

L'Union n'a pas de bonnes performances : ce article décrire à propos de comparer avec 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 : 4820ms
Fusion de dictionnaires : 16ms
HashSet et IEqualityComparer : 20ms
Union LINQ et IEqualityComparer : 24ms

1 votes

Un autre avantage de l'utilisation d'un dictionnaire de fusion -> J'ai deux listes qui reviennent des données de la 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 l'union, j'obtiens des doublons parce que l'horodatage est différent. Mais avec la fusion, je peux décider quel champ unique je veux prendre en compte dans le dictionnaire. +1

1 votes

Peut varier selon la vitesse du processeur, dépend du type de CPU dont vous disposez.

13 votes

Et à la fin de l'article, il est dit : "Je préfère LINQ Union parce qu'il communique l'intention très clairement." ;) (aussi, il n'y avait qu'une différence de 8 ms)

18voto

Robert Jeppesen Points 4541

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

13voto

Faizan S. Points 5436
    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);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X