2012-11-21 21 views
1

我有以下數據字典:如何基於列表樣式的鍵創建字符串值的連接列表?

Key Value 
1  Introduction 
1.1 General 
1.1.1 Scope 
1.2 Expectations 
2  Background 
2.1 Early Development 
... 

我希望做的是找出一種方法 - 用級聯的值來創建一個新的列表(或追加到一個數組) - 在C#基於列表式的按鍵,像這樣:

Key Value    Concatenation 
1  Introduction  Introduction 
1.1 General   Introduction - General 
1.1.1 Scope    Indroduction - General - Scope 
1.2 Expectations  Introduction - Expectations 
2  Background   Background 
2.1 Early Development Background - Early Development 
... 

有能級爲重點的沒有定數,但它總是會以數字格式。有什麼想法嗎?

+2

您可能需要將其從「扁平」數據結構轉換爲基於樹的數據結構;一旦他們在基於樹的分層視圖中,它將非常容易。 – Servy

回答

1

這顯然需要進行清理,更有效率,但你可以做到這一點很簡單地使用遞歸方法:

static string GetConcatenationRecursively(Dictionary<string, string> d, string key) 
{ 
    if (key.Length == 1) 
    { 
     return d[key]; 
    } 
    else 
    { 
     return string.Format(
      "{0} - {1}", 
      GetConcatenationRecursively(d, key.Substring(0, key.LastIndexOf('.'))), 
      d[key]); 
    } 
} 

這被稱爲是這樣的:

Dictionary<string, string> d = new Dictionary<string, string>(); 
d.Add("1", "Introduction"); 
d.Add("1.1", "General"); 
d.Add("1.1.1", "Scope"); 
d.Add("1.2", "Expectations"); 
d.Add("2", "Background"); 
d.Add("2.1", "Early Development"); 

List<Tuple<string, string, string>> list = new List<Tuple<string, string, string>>(); 
foreach (string key in d.Keys) 
{ 
    list.Add(new Tuple<string, string, string>(key, d[key], GetConcatenationRecursively(d, key))); 
} 

需求很多錯誤處理;這顯然是假設一個良好的輸入。但你應該可以從這裏拿走它。

+0

這很完美,謝謝! – bozworth

+0

對不起,我標記此帖爲提前回答。上面的方法工作的很好,但我偶爾也會有兩位數字的鍵。我應該在我原來的問題中提到這一點。我如何調整這個以實現這個目標?謝謝 – bozworth

+0

好點。編輯過的文章爲'key.LastIndexOf('。')''交換'key.Length - 2';這應該夠了吧。 – zimdanen

-2

將一個分隔符放在字符串中,您可以使用分隔符將其分開,通常爲分號(;)。但你可以使用更多。

如果您使用分號,請務必將它們從字符串中除去。

0

這個解決方案可能不是你可以想到的最漂亮的解決方案,但是如果你知道你的要求真的很簡單,你可能不想過度使用它,只是繼續做這樣的事情。方法 - 請注意,大部分代碼只是樣板以正確渲染「 - 」部分;實際的算法部分沒有太大代碼:

var dic = new Dictionary<string, string>(); 
     dic.Add("1", "Introduction"); 
     dic.Add("1.1", "General"); 
     dic.Add("1.1.1", "Scope"); 
     dic.Add("1.2", "Expectations"); 
     dic.Add("2", "Background"); 
     dic.Add("2.1", "Early Development"); 

     foreach (var kvp in dic) 
     { 
     string item = String.Empty; 

     int length = kvp.Key.Length - 2; 
     while (length > 0) 
     { 
      var parent = dic[kvp.Key.Substring(0, length)]; 
      if (!String.IsNullOrEmpty(item)) 
      item = String.Format("{0} - {1}", parent, item); 
      else 
      item = parent; 
      length -= 2; 
     } 
     if (!String.IsNullOrEmpty(item)) 
      item = String.Format("{0} - {1}", item, kvp.Value); 
     else 
      item = kvp.Value; 
     Console.WriteLine(item); 
     } 
+0

我相信你認爲這些項目將按照他們列出的順序進行處理。這不是事實。 'Dictionary'集合是無序的。你需要將它們放在'List'中,或者在迭代之前對它們進行排序(可能需要按字符串鍵長度進行排序,這應該可行)。 – Servy

+0

嗨,謝謝指出,我應該提到這一點。我的猜測是,排序將是問題的最小部分:-)因爲代碼需要重構更具表現力;我的主要觀點是,如果要求真的很簡單,那麼可以用很少的幾行代碼來解決。如果要求更爲複雜,我認爲這是值得玩弄一些更復雜的東西,比如你在對OP問題的評論中建議的方向:) – Maate

+0

還要注意,只要值是單個數字,這個效果就很好。例如,1.10.1,將不起作用。正如你所說,簡單的要求。 –

0

如果你只需要輸出顯示,使用類似Maate酒店的答案。如果你需要這個集合中,下面是一個開始(但只去一個級別):

Dictionary<string, string> d = new Dictionary<string, string>(); 
d.Add("1", "Introduction"); 
d.Add("1.1", "General"); 
d.Add("1.1.1", "Scope"); 
d.Add("1.2", "Expectations"); 
d.Add("2", "Background"); 
d.Add("2.1", "Early Development"); 

var links = from key in d.Keys 
      from subKey in d.Keys 
      where subKey.StartsWith(key) && (subKey.Length == key.Length + 2) 
      select new 
      { 
       Key = key, 
       SubKey = subKey 
      }; 

var a = from key in d.Keys 
     join link in links on key equals link.SubKey into lj 
     from sublink in lj.DefaultIfEmpty() 
     select new 
     { 
      Key = key, 
      Value = d[key], 
      Concatenation = (sublink == null ? string.Empty : d[sublink.Key] + " - ") + d[key] 
     }; 

它得到的鏈接,然後使用左從字典加盟鏈接獲得的級聯。就像我說的那樣,它只上升一級,所以這不是一個完整的解決方案。需要無限遞歸。

相關問題