2016-03-25 30 views
4

kullanarak birleştirin. C# içinde aşağıdaki yapının iki listesi var. <> 'daki her isim bir listedir. Bu iki listeye bir List<Server>'a katılmak istiyorum. Aşağıdaki sözde kod iki tür listeleri görüntüler ve sonuç gibi görünmelidir nasıl:C# İç içe geçmiş listeleri olan iki listeyi LINQ

<Servers>       <Servers> 
+...        +... 
+-- Server A,1      +-- Server A,1 
|  +...      |  +...  
|  +--<Maps>     |  +--<Maps> 
|   +--Map x    |   +--Map x 
|    +...    |    +...  
|    +--<Times>   |    +--<Times> 
|     +--Time i  |     +--Time l 
|     +--Time j  |    +--<Jumps> 
|    +--<Jumps>   |     +--Jump t 
|     +--Jump s  |     +--Jump u 
|   +--Map y    |   +--Map z 
|    +...    |    +... 
|    +--<Times>   |    +--<Jumps> 
|     +-- Time k  |     +--Jump v 
+-- Server B,1      +-- Server B,2 

Sonucu olmalıdır: Ben tam dış kullanarak çalıştı

<Servers> 
+... 
+-- Server A,1 
| +... 
| +--<Maps> 
|  +-- Map x 
|   +... 
|   +--<Times> 
|    +--Time i 
|    +--Time j 
|    +--Time l 
|   +--<Jumps> 
|    +--Jump s 
|    +--Jump t 
|    +--Jump u 
|  +-- Map y 
|   +... 
|   +--<Times> 
|    +--Time k 
|  +-- Map z 
|   +... 
|   +--<Jumps> 
|    +--Jump v 
+-- Server B,1 
+-- Server B,2 

linq ile katılmak ama sonuç ne de değildi Aynı anahtarlara sahip olan sunucuların birbirleriyle eşleşmediğini anlamadığım için, aynı sunucudan her zaman farklı verilerle çoğaltılmıştım. O zaman bunu linq ile yapmaya çalışmayı bıraktım ve listeleri el ile birleştirmek için sadece döngüler kullandım.

Aşağıdaki kod bana istenen sonuç listesini verir. Şimdilik bunu yapmak için daha iyi bir yol bulana kadar kullanacağım. Bunu linq ile basit/kısa bir yol var mı? Lambda ifadelerini kullanarak?

foreach (Server importServer in oImportList) 
     { 
      if (!CoreList.Contains(importServer)) 
      { 
       CoreList.Add(importServer); 
       continue; 
      } 

      Server coreServer = CoreList.FirstOrDefault(o => o.Equals(importServer)); 
      coreServer.Name = importServer.Name; 
      coreServer.KZTimerVersion = importServer.KZTimerVersion; 
      foreach(Map importMap in importServer.Maps) 
      { 
       if (!coreServer.Maps.Contains(importMap)) 
       { 
        coreServer.Maps.Add(importMap); 
        continue; 
       } 
       Map coreMap = coreServer.Maps.FirstOrDefault(o => o.Equals(importMap)); 
       coreMap.Jumps.Concat(importMap.Jumps); 
       coreMap.Times.Concat(importMap.Times); 
      } 
     } 
+0

Doğru fikre sahip olduğunuzu düşünüyorum. İç içe geçmiş 'Join's yanlış parametreleri geçtiniz gibi görünüyor! Örneğin, "Maps" birleşiminde 'coreServer.Maps' ve' oImportList''e katılmaya çalışıyorsunuzdur… Bunun “coreServer.Maps” ve “importServer.Maps” olması gerektiğinden şüpheleniyorum. – 31eee384

+0

Yardımınızla çalışan kodu alabildim, ancak sonucun istediğim liste olmadığını gördüm. Sadece her iki listede de bulunan öğeleri içeriyordu. – schm0ftie

+0

Ah, pardon ... Ben sadece çok nadiren 'Join' kullandım, bu yüzden karıştırdım. Sizin için çalışabilecek 'GroupBy' ve' Select' kullanarak bir yanıtı geri aldım. Daha önce sildim çünkü yanlış yolda gittiğimi düşündüm. – 31eee384

cevap

0

Sen .Union için arıyor olabilir, ama bu yüzden gerçekten gereken sanmıyorum iç içe listeleri ile uğraşmaz. Ben tam bir örnek kurmak - yapı sizinkiyle aynı olmasa da ben kolayca çekirdek linq uygulayabilirsiniz düşünüyorum:

using System; 
using System.Collections.Generic; 
using System.Linq; 

public class Map 
{ 
    public string Name { get; set; } 
    public IEnumerable<MapProperty> Properties { get; set; } 
} 

public class MapProperty 
{ 
    public string Name { get; set; } 
} 

public class Test 
{ 
    public static IEnumerable<Map> Merge(IEnumerable<Map> a, IEnumerable<Map> b) 
    { 
     return a.Concat(b) 
      .GroupBy(map => map.Name) 
      .Select(mg => new Map 
      { 
       Name = mg.Key, 
       Properties = mg.SelectMany(v => v.Properties) 
        .GroupBy(p => p.Name) 
        .Select(pg => new MapProperty { Name = pg.Key }) 
      }); 
    } 

    public static void Main() 
    { 
     var mapsA = new[] 
     { 
      new Map 
      { 
       Name = "MapA", 
       Properties = new[] 
       { 
        new MapProperty { Name = "Jumps" }, 
        new MapProperty { Name = "Hops" }, 
       } 
      }, 
      new Map 
      { 
       Name = "MapB", 
       Properties = new[] 
       { 
        new MapProperty { Name = "Jumps" }, 
        new MapProperty { Name = "Skips" }, 
       } 
      } 
     }; 
     var mapsB = new[] 
     { 
      new Map 
      { 
       Name = "MapA", 
       Properties = new[] 
       { 
        new MapProperty { Name = "Jumps" }, 
        new MapProperty { Name = "Times" }, 
       } 
      }, 
      new Map 
      { 
       Name = "MapC", 
       Properties = new[] 
       { 
        new MapProperty { Name = "Jumps" }, 
        new MapProperty { Name = "Skips" }, 
       } 
      } 
     }; 

     var mapsC = Merge(mapsA, mapsB); 

     foreach (var map in mapsC) 
     { 
      Console.WriteLine($"{map.Name}"); 
      foreach (var prop in map.Properties) 
      { 
       Console.WriteLine($"\t{prop.Name}"); 
      } 
     } 
    } 
} 

çıkışı:

MapA 
    Jumps 
    Hops 
    Times 
MapB 
    Jumps 
    Skips 
MapC 
    Jumps 

Merge önemli bit . İlk önce a ve b'u tek bir listeye koyar, daha sonra aynı ada sahip haritaların GroupBy isim formları gruplarını oluşturur. Select her grubu alır ve bu gruptaki tüm Maps içeriğiyle yeni bir yapar (bu birleştirme!). Sonra aynı şeyi yeni birleştirilmiş haritanın içeriğine yaptım ve MapProperty s gruplarını birleştirip birleştirin/birleştirin. Özel durumunuzda, her şeyi birleştirmek için biraz daha fazla çalışmaya ve seviyeye ihtiyacınız olacaktır. Ağacın her düzeyi için Merge yöntemini yapmanın bir yolunu bulmayı ve her üst düzeyden bir sonraki seviyeyi çağırmayı öneririm, böylece bir masif linq zinciri ile bitmezsiniz.

İlgili konular