LINQ Iscriviti a 2 elenchi s

Prefazione: non capisco cosa faccia questo:

o => o.ID, i => i.ID, (o, id) => o 

Quindi vai piano con me. 🙂


Ho 2 liste che ho bisogno di unire insieme:

 // list1 contains ALL contacts for a customer. // Each item has a unique ID. // There are no duplicates. ContactCollection list1 = myCustomer.GetContacts(); // list2 contains the customer contacts (in list1) relevant to a REPORT // the items in this list may have properties that differ from those in list1. /*****/// eg: /*****/ bool SelectedForNotification; /*****/// may be different. ContactCollection list2 = myReport.GetContacts(); 

Devo creare un terzo ContactCollection che contenga tutti i contatti in list1 ma con le proprietà degli elementi in list2 , se l’elemento è nell’elenco [2] ( list3.Count == list1.Count ).


Devo sostituire tutti gli elementi in list1 con gli articoli in list2 cui gli elementi in list1 hanno gli ID degli articoli in list2 . L’elenco risultante ( list3 ) dovrebbe contenere lo stesso numero di elementi in list1 .

Mi sento come se non avessi alcun senso. Quindi, per favore fai domande nei commenti e proverò a chiarire.

I join non sono così difficili, ma il tuo problema potrebbe probabilmente usare qualche ulteriore spiegazione.

Per unire due liste, potresti fare qualcosa di simile

 var joined = from Item1 in list1 join Item2 in list2 on Item1.Id equals Item2.Id // join on some property select new { Item1, Item2 }; 

questo darà un IEnumerable<'a> , dove’ a è un tipo anonimo che tiene un object da list1 e il relativo object da list2. È quindi ansible scegliere le proprietà degli oggetti da utilizzare secondo necessità.

Per ottenere il risultato in un elenco concreto, è sufficiente una chiamata a .ToList (). Puoi farlo

 var list3 = joined.ToList(); // or var list3 = (from Item1 in list1 join Item2 in list2 on Item1.Id equals Item2.Id // join on some property select new { Item1, Item2 }).ToList(); 

Per fare un join a sinistra per selezionare tutti gli elementi da list1 anche senza una corrispondenza in list2, puoi fare qualcosa di simile

 var list3 = (from Item1 in list1 join Item2 in list2 on Item1.Id equals Item2.Id // join on some property into grouping from Item2 in grouping.DefaultIfEmpty() select new { Item1, Item2 }).ToList(); 

Questo ti darà una lista dove Item1 è uguale all’elemento dal primo elenco e Item2 sarà uguale all’elemento corrispondente dal secondo elenco o predefinito, che sarà nullo per un tipo di riferimento.

Ecco cosa mi è venuto in mente (basato su questo ):

  List list3 = (from item1 in list1 join item2 in list2 on item1.ContactID equals item2.ContactID into g from o in g.DefaultIfEmpty() select o == null ? item1 :o).ToList(); 

La mia parte preferita è la faccina dal naso grosso

:o)

Grazie per l’aiuto!

Ecco un DotNetFiddle con un gruppo Linq Join

 using System; using System.Collections; using System.Collections.Generic; using System.Linq; class Order { public int Id; public string Name; public Order(int id, string name) { this.Id = id; this.Name = name; } } class OrderItem { public int Id; public string Name; public int OrderId; public OrderItem(int id, string name, int orderId) { this.Id = id; this.Name = name; this.OrderId = orderId; } } List orders = new List() { new Order(1, "one"), new Order(2, "two") }; List orderItems = new List() { new OrderItem(1, "itemOne", 1), new OrderItem(2, "itemTwo", 1), new OrderItem(3, "itemThree", 1), new OrderItem(4, "itemFour", 2), new OrderItem(5, "itemFive", 2) }; var joined = from o in orders join oi in orderItems on o.Id equals oi.OrderId into gj // gj means group join and is a collection OrderItem select new { o, gj }; // this is just to write the results to the console string columns = "{0,-20} {1, -20}"; Console.WriteLine(string.Format(columns, "Order", "Item Count")); foreach(var j in joined) { Console.WriteLine(columns, joName, j.gj.Count() ); } 

Sembra che tu non abbia davvero bisogno di un full-join. Potresti invece fare un semi-join, controllando ogni contatto nella lista 2 per vedere se è contenuto nella lista 1:

ContactCollection list3 = list2.Where(c => list1.Contains(c));

Non so quanto siano grandi le vostre liste, ma notate che questo approccio ha complessità O ( nm) a meno che list1 non sia ordinato o supporti ricerche veloci (come in un hashset), nel qual caso potrebbe essere efficiente come O (n log (m)) o riscritto come unione di unione ed essere O (n).