2013-01-16 28 views
5

Her biri bir nesne listesi döndüren iki sorgum var.Belirli bir özellikte iki liste nasıl birleştirilir?

List<A> list1 = (....query...) 
List<A> list2 = (....query...) 

"A", bir nesne modelidir.

Her iki sorgunun da hemen hemen aynı nesneler döndürülür, ancak farklı özellikler ayarlanmış olur.

List<A> finalLis = list1 join list2 on elemList1.somePropID == elemList2.somePropID 

basit C# tarzında böyle bir şey olurdu: Ben çiftleri kaldırmak istediğiniz

şey böyle

Temelde nesne A'nın bir özelliği dayalı tek bir liste haline birleştirmek:

foreach(elem1 : list1) { 
    foreach(elem2: list1) { 
     if(elem1.someID == elem2.someID) { 
      elem1.someProp = elem2.someProp 
      elem1.otherProp = elem2.otherProp 
     } 
    } 
} 

Bunu böyle yapmak istemiyorum çünkü eminim ki linq'de daha zarif bir yol var.

Herhangi bir öneriniz varsa lütfen bana bildirin.

+0

ayarladığınız sonucu, ilk koleksiyonunda herhangi bir öğe kimliği eşleşmiyor ikinci koleksiyonundan çizelgesine istiyor musunuz? – mipe34

+0

no .... ilk listedeki öğeler, ikinci listedeki öğelerle neredeyse aynıdır. Ideea, ilk listede bazı özellikler ayarlanmamıştır, ancak bu değerler kendi meslektaşlarında bulunabilir. Son liste ilk listedir, ancak tüm özellikler – cmg

cevap

1

Linq güncellenmesi ile seçilmesi ile yardımcı ama olamaz. Yani foreach ifadesinden kurtulmayacaksınız. Yani senin görevin böyle linq ile yazılmış olabilir:

//the query is like LEFT JOIN in SQL 
var query = from x in list1 
      join y in list2 on x.IDItem equals y.IDItem 
      into z 
      from q in z.DefaultIfEmpty() 
      select new {IOne = x, ITwo = q}; 
foreach (var pair in query) 
{ 
    if (pair.ITwo != null) // && pair.IOne.OneProperty != null 
     pair.IOne.OneProperty = pair.ITwo.TwoProperty; 
} 

var resultList = query.Select(x => x.IOne).ToList(); 

Sonuçlara here kontrol edebilirsiniz.

0

bu deneyin:

List<A> list = (from e1 in list1 
      join e2 in list2 
      on e1.ID equals e2.ID 
      select new A 
      { 
       ID = l2.ID, 
       someProp1 = l2.someProp1, 
       someProp2 = l2.someProp2 
      }).ToList(); 

Sonra tüm unsurları ile üçüncü liste olurdu.

Bu bağlantı yardımcı olabilir: LINQ Join 2 List<T>s

+1

olarak ayarlanmıştır. Her listeden (benzersiz ID ile) benzersiz nesneler içermez. Ayrıca mevcut güncelleme yerine yeni nesneler yaratacaktır. –

+0

Ancak, farklılıkların liste1'e ayarlanmamış ve list2'ye ayarlanmayan bazı özellikler olduğunu söyledi. Ve kod örneğinin yazıldığı şekilde üçüncü bir liste istediğini öğrendim. –

0

Linq sorgulama için değil güncellenmesi olduğunu. Birleştirmeyi basitleştirebilirsiniz, ancak güncellemeyi yapmak için hala dönmeniz gerekir. gibi

şey:

List<A> finalList = 
    from item1 in list1 
    join item2 in list2 on item1.somePropID equals item2.somePropID 
    select new{Item1 = item1, Item2 = item2}; 

foreach(var item in finalList) 
{ 
    item.Item2.someProp1 = item.Item1.someProp1; 
    item.Item2.someProp2 = item.Item1.someProp2; 
} 
+1

Aynı şey - katılmayan kimlikler son listede yok. –

+0

Tamam Bunu açıklayan yorumu görmedim. –

0

LINQ kullanmak çok doğru.

cevaplar burada tüm verilen C# eşdeğer pasajı çok verimsiz olduğunu dışında pasajı ve list1.Length * list2.Length operasyonlarını neden olacaktır. Kullanılması LINQ katılır

çok daha etkili ve sonuç kabaca list1.Length + list2.Length operasyonlarda yer almaktadır.

bir sözlük

// create a dict so that you can lookup things in item1 based on id 
var list1IdToADict = list1.ToDictionary(a => a.id); 

//filter out things not in both lists (join on there id) 
var joinedList2 = list2.Where(a => list1IdToADict.ContainsKey(a.id)); 

Diğer cevaplar kullanarak böyle bir şey yapacak id katılmak daha elagant ama sen bu şekilde yapmak istiyorsa sen

foreach(var a in joinedList2){ 
    a.someProp = list1IdToADict[a.id].someProp; 
    a.otherProp = list1IdToADict[a.id].otherProp; 
} 
ile bitiremeden Bunun nedeni
0

List<T> üzerinden herhangi bir çözüm, listelerin sıralanması gerektiğinden N * Log (n) öğesinde gerçekleştirecektir.

Modelinizde eşitlik üyelerini uygulayın ve bunun yerine bir HashSet<T> kullanın.

Bu, hem karmaşıklıkta hem de ayırmalarda optimaldir.

var set1 = new HashSet<Model> 
{ 
    new Model(0, "000"), 
    new Model(2, "222"), 
    new Model(4, "444"), 
}; 

var set2 = new HashSet<Model> 
{ 
    new Model(1, "111"), 
    new Model(2, "2222"), 
    new Model(3, "333"), 
}; 

set1.ExceptWith(set2); 
set1.UnionWith(set2); 

Eklemek için, sonuç kümesi olarak üzerine yazma setini kullanmak daha hızlı olacaktır. Yukarıdaki örnekteki

set2.UnionWith(set1); 

Sınıf Model:

class Model 
{ 
    public readonly int Id; 
    public string Data; 

    public Model(int id, string data) 
    { 
     Id = id; 
     Data = data; 
    } 

    public override int GetHashCode() 
    { 
     return Id; 
    } 

    protected bool Equals(Model other) 
    { 
     return Id == other.Id; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     return obj.GetType() == GetType() && Equals((Model) obj); 
    } 
} 
İlgili konular