2013-03-15 86 views
-1

我有一個字符串的集合:構建層次C#

"Alberton;Johannesburg" 
"Allendale;Phoenix" 
"Brackenhurst;Alberton" 
"Cape Town;" 
"Durban;" 
"Johannesburg;" 
"Mayville;Durban" 
"Phoenix;Durban" 
"Sandton;Johannesburg" 

,我想構建成一個層次結構在最快的方式,如:

  • 約翰內斯堡

    • Alberton
      • Brac kenhurst
    • 桑頓
  • 開普敦

  • 德班

    • 鳳凰
      • Allandale
    • 梅維爾

目前我有嵌套的for循環和檢查,但希望我能有一個LAMBDA查詢實現這一目標?

上述字符串在列表中。

+2

你目前的代碼是什麼? – Maarten 2013-03-15 11:35:43

+1

你現在的代碼有什麼樣子? – LukeHennerley 2013-03-15 11:35:48

+2

因爲你認爲單線拉姆達會天生更快?那是錯的。 – 2013-03-15 11:35:51

回答

1

我準備λ狀解決方案,但你真的應該想,如果它更可讀/高效然後你目前的一個:

助手擴展方法:

public static class ChildrenGroupExtensions 
{ 
    public static List<CityInfo> GetChildren(this IEnumerable<IGrouping<string, City>> source, string parentName) 
    { 
     var cities = source.SingleOrDefault(g => g.Key == parentName); 
     if (cities == null) 
      return new List<CityInfo>(); 

     return cities.Select(c => new CityInfo { Name = c.Name, Children = source.GetChildren(c.Name) }).ToList(); 
    } 
} 

輔助類:

public class City 
{ 
    public string Name { get; set; } 
    public string Parent { get; set; } 
} 

public class CityInfo 
{ 
    public string Name { get; set; } 
    public List<CityInfo> Children { get; set; } 
} 

用法:

var groups = (from i in items 
       let s = i.Split(new[] { ';' }) 
       select new City { Name = s[0], Parent = s[1] }).GroupBy(e => e.Parent); 


var root = groups.GetChildren(string.Empty); 

哪裏items是您List<string>

你可以看看有這樣的一個簡單的輔助方法的結果:

private static void PrintTree(List<CityInfo> source, int level) 
{ 
    if (source != null) 
    { 
     source.ForEach(c => 
     { 
      Enumerable.Range(1, level).ToList().ForEach(i => Console.Write("\t")); 
      Console.WriteLine(c.Name); 
      PrintTree(c.Children, level + 1); 
     }); 
    } 
} 

而且結果是:

Cape Town 
Durban 
     Mayville 
     Phoenix 
       Allendale 
Johannesburg 
     Alberton 
       Brackenhurst 
     Sandton 
1

您尚未指定任何特定的數據結構,因此我只是使用了一個名爲Area的類以及它自己的子級列表。此外,它在2行linq。也沒有檢查,看看一個地區是否是代碼是2個獨立父母的孩子。下面是我使用的測試代碼(相關行之間的等號評論):

[TestFixture] 
public class CitiesTest 
{ 
    [Test] 
    public void Test() 
    { 
     var strings = new List<string> 
      { 
       "Alberton;Johannesburg", 
       "Allendale;Phoenix", 
       "Brackenhurst;Alberton", 
       "Cape Town;", 
       "Durban;", 
       "Johannesburg;", 
       "Mayville;Durban", 
       "Phoenix;Durban", 
       "Sandton;Johannesburg" 
      }; 

     //=================================================== 
     var allAreas = strings.SelectMany(x=>x.Split(';')).Where(x=>!string.IsNullOrWhiteSpace(x)).Distinct().ToDictionary(x=>x, x=>new Area{Name = x}); 

     strings.ForEach(area => 
      { 
       var areas = area.Split(';'); 

       if (string.IsNullOrWhiteSpace(areas[1])) 
        return; 

       var childArea = allAreas[areas[0]]; 
       if (!allAreas[areas[1]].Children.Contains(childArea)) 
        allAreas[areas[1]].Children.Add(childArea); 

       childArea.IsParent = false; 
      }); 

     var result = allAreas.Select(x=>x.Value).Where(x => x.IsParent); 
     //=================================================== 
    } 

    public class Area 
    { 
     public string Name; 
     public bool IsParent; 
     public List<Area> Children { get; set; } 

     public Area() 
     { 
      Children = new List<Area>(); 
      IsParent = true; 
     } 
    } 
}