7
votes

Fusionner deux listes en C # et fusionner des objets avec le même ID dans un élément de liste

J'ai déjà pensé à la façon dont je vais résoudre ce problème en roulant ma propre solution, mais je me demandais si .net a déjà la fonctionnalité de ce que j'essaie de monter - si oui, je préfère utiliser quelque chose Intégré.

Supposons que j'ai deux instances d'un objet widget code>, appelons-les partita ​​code> et partie code>. Les informations de chacun ont été recueillies à partir de deux services Web différents, mais les deux ont des identifiants correspondants. P> xxx pré>

Je veux fusionner celles-ci pour créer ce qui suit: p>

List<Widget> Result = PartA.MergeWith(PartB).MergeObjectsOn(Widget.ID).toList();


1 commentaires

Juste une façon vraiment non intelligente de le faire. Complètement manuel: boucle à travers chaque liste et créer une nouvelle liste d'objets fusionnés - que j'ai également fusionné manuellement (c'est-à-dire codé dur). Cela fait le travail, mais ça craint vraiment et sera gênant de maintenir. Je cherche une meilleure façon.


3 Réponses :


13
votes

Vous pouvez écrire votre (s) méthode (s) d'extension), quelque chose comme ceci: xxx

icanmerge est comme: xxx < / Pré>

Mise en œuvre, par exemple Comme: xxx

alors c'est aussi simple que partita.mergewith (partb) .tolist () .


4 commentaires

Façon de faire le mile supplémentaire, tim! J'attendais un point dans la bonne direction, mais vous semblez avoir fourni une solution (et bien mieux que ce que j'utilise actuellement). Merci beaucoup :). Je vais essayer cela et revenir à vous avec un "accepter".


Quand j'ai essayé cela, cela ne me permet que de fusionner contre l'objet (par exemple, un widget), pas contre toute la liste, ce qui signifierait faire une forise et faire la fusion de chaque article (après avoir trouvé un match pour chacun). À peu près sûr que ce n'est pas c'était censé être utilisé, mais pourquoi ne pas fusionner l'une de mes options comme une extension pour des listes ienumérables?


@mppowe avez-vous changé-le à cette source T au lieu de de cette source source ? C'est la seule chose que je puisse penser à cela expliquerait ce que vous décrivez.


Peu importe ... Je ne sais pas pourquoi ce n'était pas montrant auparavant, maintenant c'est. Peut-être que je n'ai pas donné à Intellisense une chance de se rattraper ou de quelque chose. Quoi qu'il en soit, oui ça a fonctionné. Une chose à noter est que si les listes sont de tailles différentes, la première liste (Parta dans l'exemple ci-dessus) doit être la plus petite. Sinon, vous obtenez une phrase clésFoundException. Merci encore pour le code ci-dessus Tim, c'est assez cool



2
votes

Si vos listes sont une pour une (c'est-à-dire le même nombre d'éléments et chaque élément de la liste Parta contient une correspondance dans la liste Partb), je considérerais ensuite le zip extension. Notez que ZIP n'exige pas que chaque liste ait le même nombre d'éléments. Toutefois, si vous ne pouvez pas compter sur des éléments "associe" avec des identifiants correspondants, mon approche simpliste ne fonctionnera pas.

vous pouvez faire quelque chose comme ceci: xxx

Si vous souhaitez que votre LINQ soit plus propre, vous pouvez encapsuler le widget individuel de la logique dans une méthode de fonction ou d'extension. qu'au lieu du délégué en ligne.


0 commentaires

0
votes
var source = new List<MediaFolder>
            {
                new MediaFolder
                    {
                        Id = "Id1",
                        Name = "Name1",
                        Path = "Path1"
                    },
                new MediaFolder
                    {
                        Id = "Id2",
                        Name = "Name2",
                        Path = "Path2"
                    },
                new MediaFolder
                    {
                        Id = "Id3",
                        Name = "Name3",
                        Path = "Path3"
                    },
                new MediaFolder
                    {
                        Id = "Id4",
                        Name = "Name4",
                        Path = "Path4"
                    },
                new MediaFolder
                    {
                        Id = "Id5",
                        Name = "Name5",
                        Path = "Path5"
                    },
                new MediaFolder
                    {
                        Id = "Id6",
                        Name = "Name6",
                        Path = "Path6"
                    }
            };

        var target = new List<MediaFolder>
            {
                new MediaFolder
                    {
                        Id = "Id1",
                        Name = "Actualizado en el objeto",
                        Path = "Path1"
                    },
                    //Id2 eliminado
                new MediaFolder
                    {
                        Id = "Id3",
                        Name = "Name3",
                        Path = "Actualizado tambien"
                    },
                new MediaFolder
                    {
                        Id = "Id4",
                        Name = "Name4",
                        Path = "Path4"
                    },
                new MediaFolder
                    {
                        Id = "Id5",
                        Name = "Name5",
                        Path = "Path5"
                    },
                new MediaFolder
                    {
                        Id = "Id6",
                        Name = "Name6",
                        Path = "Path6"
                    },
                     new MediaFolder
                    {
                        Id = "Id7",
                        Name = "Nuevo Item 7",
                        Path = "Nuevo Item 7"
                    }
            };

        var merge = source.Merge(target, (x, y) => x.Id == y.Id);

        var toUpdate = merge.Matched((x, y) => x.Name != y.Name | x.Path != y.Path)
            .ToArray();

        var toDelete = merge.NotMatchedBySource();
        var toInsert = merge.NotMatchedByTarget();

        Assert.AreEqual(2, toUpdate.Count());
        Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id1" & x.Target.Id == "Id1") > 0);
        Assert.IsTrue(toUpdate.Count(x => x.Source.Id == "Id3" & x.Target.Id == "Id3") > 0);

        Assert.AreEqual("Id7", toInsert.First().Id);
        Assert.AreEqual("Id2", toDelete.First().Id);

0 commentaires