Ici, j'ai 2 listes du même type d'objet.
List mergedSet = [{old1, null}, {old2, new2}, {old3, new3}, {null, new4}];
Je souhaite fusionner les deux listes, en conservant également l'origine de la liste dont elles proviennent.
Le résultat attendu comme ci-dessous:
object = {id: xxx, ...} // attribute "id" is used to find the identical obj List oldSet = [old1, old2, old3]; List newSet = [new2, new3, new4]; // old2 = {id= 2, result = 5, ...} // new2 = {id= 2, result = 1, ...} // expected result = {oldSet: old2; newSet: new2}
Je pense utiliser LINQ C # pour cela, mais coincé quelque part.
Veuillez conseiller.
Merci! :)
5 Réponses :
Essayez quelque chose comme ceci:
List<string> oldSet = new List<string>() {"old1", "old2", "old3"}; List<string> newSet = new List<string>() {"new2", "new3", "new4"}; var results = oldSet.Select((x,i) => new { oldSet = x, newSet = newSet[i]}).ToList();
La question est un peu brisée, mais il semble qu'il ne se contente pas de les compresser, mais qu'il crée des paires en fonction des nombres dans les données.
Voici un code qui fait ce que vous voulez en utilisant Linq. Il parcourt en gros toute l'ancienne liste et ajoute des paires à la liste fusionnée en recherchant des correspondances dans la nouvelle liste (et en ajoutant null
comme deuxième élément si aucune correspondance n'a été trouvée). Ensuite, il parcourt les éléments restants dans la nouvelle liste et les ajoute avec null
pour le premier élément. Il sélectionne un type dynamique avec deux propriétés: OldSet
et NewSet
, afin que vous sachiez d'où vient chaque élément.
Le code de fusion est simplement:
XXX
Ceci est basé sur la classe d'objets suivante:
foreach (var item in mergedSet) { Console.WriteLine($"{item.NewSet},{item.OldSet}"); }
Nous créons nos listes:
List<Item> oldSet = new List<Item> { new Item {id = 1, result = "old"}, new Item {id = 2, result = "old"}, new Item {id = 3, result = "old"}, }; List<Item> newSet = new List<Item> { new Item {id = 2, result = "new"}, new Item {id = 3, result = "new"}, new Item {id = 4, result = "new"}, };
Exécutez le code de fusion (tout premier extrait de code), puis affichez les résultats:
class Item { public int id { get; set; } public string result { get; set; } public override string ToString() { return $"{result}{id}"; } }
Sortie
C'est beaucoup trop de code pour cette tâche ... Linq existe spécifiquement pour faire ce genre de chose. Il est inutile d'utiliser des tuples ici, quelques jointures ou une union feront très bien l'affaire.
Vous aviez raison, j'ai corrigé mon code, supprimé les commentaires non pertinents ... :)
@DrunkenCodeMonkey Cool. J'ai également corrigé le mien pour réduire le code de fusion de 2 lignes à une ligne (et j'ai également utilisé des types dynamiques) au cas où c'est pourquoi quelqu'un a voté contre.
Vous pouvez quitter rejoindre les deux listes. J'ai modifié la réponse car vous devez en fait quitter deux fois la jointure, l'union et appliquer une sélection distincte pour obtenir les cas où oldSet = null et pas de doublons ...
var mergedSet = (from o in oldSet join n in newSet on o.id equals n.id into ns from n in ns.DefaultIfEmpty() select new { OldSet = o, NewSet = n }) .Union(from n in newSet join o in oldSet on n.id equals o.id into os from o in os.DefaultIfEmpty() select new { OldSet = o, NewSet = n }) .Distinct();
Peut-être exagéré, mais si vous voulez vraiment utiliser LINQ
List<Item> oldSet = new List<Item> { new Item {id = 1, result = "old"}, new Item {id = 2, result = "old"}, new Item {id = 3, result = "old"}, }; List<Item> newSet = new List<Item> { new Item {id = 2, result = "new"}, new Item {id = 3, result = "new"}, new Item {id = 4, result = "new"}, }; var resultL = oldSet.GroupJoin( newSet, o => o.id, n => n.id, (o,n) => new { Old = o, New = n }) .SelectMany( n => n.New.DefaultIfEmpty(), (o,n) => new Tuple<Item,Item>(o.Old,n)); var resultR= newSet.GroupJoin( oldSet, n => n.id, o=> o.id, (n,o) => new { Old = o, New = n }) .SelectMany( o=> o.Old.DefaultIfEmpty(), (n,o) => new Tuple<Item,Item>(o,n.New)); var result = resultL.Union(resultR).Distinct();
Dans ce cas, vous devez utiliser deux GroupJoin
et l ' Union
les résultats.
Regardez le code suivant:
var res1 = oldSet.GroupJoin(newSet, o => o, k => k, (x, y) => { var yy = y.FirstOrDefault(); return new { X = x, Y = yy }; }); var res2 = newSet.GroupJoin(oldSet, o => o, k => k, (x, y) => { var yy = y.FirstOrDefault(); return new { X = yy, Y = x }; }); var result = res1.Union(res2).ToList();// Your result is here
déjà entendu parler de Dictionary? ou tableaux multidimensionnels?
Quel est le
Type
demergedSet
? S'agit-il d'unList>
?Je pense que le type de résultat peut être facultatif. Tant que je peux dire que cet élément provient de oldSet ou newSet, et combinez ceux avec le même identifiant. Merci à tous pour les indices
Ce serait génial si vous pouviez fournir un exemple reproductible minimal . Votre code, tel quel, ne se compile pas.
Les détails suivants manquent dans votre question pour fournir une réponse utile: (1) Les éléments
oldSet
etnewSet
auront-ils les éléments dans le même ordre, c'est-à-dire siL'identifiant
des éléments dans le même index ne correspond pas. Est-il sûr de supposer que l'élément n'existe pas dans l'autre liste? (2) Quelle séquence doit être conservée? c'est-à-dire si les deux listes ont tout distinct et aucune correspondance pour aucun élément, quelle devrait être la sortie?@MatJ (1) non, la séquence peut être aléatoire. et oui, si l'un n'existe pas dans l'autre liste, il est prudent de dire qu'il n'existe pas et de renvoyer un null. (2) la séquence d'objets dans la liste n'est pas importante. La "séquence" mentionnée en question fait référence à la liste de résultats finale, le premier élément proviendra de l'ancienSet, le second du newSet. J'espère que cela clarifie
Donnez un exemple de sortie requise pour deux listes distinctes. Comme list1 = [1,2,3,4,5], list2 = [10,20,30]. Quelle devrait être la sortie?