2011-09-12 41 views
1

我只想問:這是一個方法體中的多鍵詞典的高效代碼嗎?

  1. 下面的代碼是有效的嗎?
  2. 有沒有更好的方法來處理這個問題?
  3. 如何編碼是否需要表名/字段名對的附加值?

我們需要使用包含諸如(TableName,FieldName,FieldValue)之類的多鍵字典。

我搜索了一些答案,但我發現迄今爲止不適用於我們的設置。我們使用3.5,所以沒有可用的Tuple。我們還將此腳本邏輯與只允許在方法體內進行編碼的應用程序集成,因此我們受到限制,無法創建單獨的類/結構等。我們的設置是C#/ VS 2010.

任何幫助表示讚賞。提前致謝!

Dictionary<string, Dictionary<string, string>> tableList = new Dictionary<string, Dictionary<string, string>>(); 
Dictionary<string, string> fieldList = new Dictionary<string, string>(); 

// add fields to field list, then add the field lists to the corresponding table list 
// clear field list for next table 
// values are just hardcoded here to simplify, but is being read from actual objects in the application 

fieldList.Add("Field1", "abc"); 
fieldList.Add("Field2", "def"); 
fieldList.Add("Field3", "ghi"); 
fieldList.Add("Field4", "jkl"); 

tableList.Add("Table1", new Dictionary<string, string>(fieldList)); 
fieldList.Clear(); 

fieldList.Add("Field1", "xyz"); 
fieldList.Add("Field2", "uvw"); 
fieldList.Add("Field3", "rst"); 

tableList.Add("Table2", new Dictionary<string, string>(fieldList)); 
fieldList.Clear(); 

fieldList.Add("Field1", "123"); 
fieldList.Add("Field2", "456"); 

tableList.Add("Table3", new Dictionary<string, string>(fieldList)); 
fieldList.Clear(); 

// Display tables and corresponding fields       

foreach (KeyValuePair<string, Dictionary<string, string>> fieldList4 in tableList) 
{ 
    foreach (KeyValuePair<string, string> fieldList5 in fieldList4.Value) 
    { 
     txtMessage.Text = txtMessage.Text + "\r\nTable=" + fieldList4.Key + ", Field=" + fieldList5.Key + " - " + fieldList5.Value; 
    } 
} 

// Try to find tables and fields in the lists, and list the value if found 

string tableToFind = "Table2"; 
string fieldToFind = "Field2"; 
Dictionary<string, string> tableFields = new Dictionary<string, string>(); 

if (tableList.Keys.Contains(tableToFind) == true) 
{ 
    txtMessage.Text = txtMessage.Text = "\r\nTable=" + tableToFind + " exist in table list"; 
    tableList.TryGetValue(tableToFind, out tableFields); 

    if (tableFields.Keys.Contains(fieldToFind) == true) 
    { 
     foreach(KeyValuePair<string, string> fieldData in tableFields) 
     { 
      if (fieldData.Key == fieldToFind) 
      { 
       txtMessage.Text = txtMessage.Text + "\r\nTable=" + tableToFind + ", Field=" + fieldData.Key + 
                " with value=" + fieldData.Value + " exist in table list"; 
       break; 
      } 
     } 
    } 
} 
+0

爲什麼不利用Sugar提供的一些有用的語法? – ChaosPandion

+0

使用單個字典完成此操作的一種方法是將表鍵和字段鍵合併成一個字符串,例如。 「表1 |字段1」。不知道這是否更有效。 –

+0

如果您對弱類型數據集語義有要求,是否有任何理由不使用這些類?如果可能的話,我認爲最好的做法是使用強類型的解決方案。 –

回答

2

代碼中存在一系列問題和低效率。

  1. 如果您要創建多個字典,請直接創建字典。不要使用單獨的實例來填充值並從中複製。

  2. 不要在像這樣的循環中使用字符串連接。使用StringBuilder或其他類似的機制來建立你的字符串。你已經有了你的值在一個集合中,所以使用String.Join()與LINQ一起會清除它。

  3. 從字典中獲取值的方法很尷尬,至少可以說。通常你只用TryGetValue()來嘗試讀取密鑰。你的代碼使用不正確。如果您要檢查字典中是否存在密鑰(使用Contains()),則使用TryGetValue()沒有意義。更糟糕的是,你做了這個然後通過遍歷鍵值對在內部字典中手動搜索關鍵字。

的典型模式是這樣的:

DictValueType value; 
if (myDict.TryGetValue(key, out value)) 
{ 
    // key was in the dictionary, the value is stored in the `value` variable 
} 

你可以寫很多更有效地這樣的代碼:

var tableList = new Dictionary<string, Dictionary<string, string>> 
{ 
    { "Table1", new Dictionary<string, string> 
       { 
        { "Field1", "abc" }, 
        { "Field2", "def" }, 
        { "Field3", "ghi" }, 
        { "Field4", "jkl" }, 
       } 
    }, 
    { "Table2", new Dictionary<string, string> 
       { 
        { "Field1", "xyz" }, 
        { "Field2", "uvw" }, 
        { "Field3", "rst" }, 
       } 
    }, 
    { "Table3", new Dictionary<string, string> 
       { 
        { "Field1", "123" }, 
        { "Field2", "456" }, 
       } 
    }, 
}; 

// Display tables and corresponding fields 
txtMessage.Text = String.Join("\r\n", 
    tableList.SelectMany(table => 
     table.Value.Select(fieldList => 
      String.Format("Table={0}, Field={1} - {2}", 
       table.Key, fieldList.Key, fieldList.Value) 
     ) 
    ).ToArray() 
); 

// (I hope you have this in a separate method) 
// Try to find tables and fields in the lists, and list the value if found 
string tableToFind = "Table2"; 
string fieldToFind = "Field2"; 

var builder = new StringBuilder(txtMessage.Text); // mostly useful if you have a 
                // lot of different strings to add 
Dictionary<string, string> foundTable; 
if (tableList.TryGetValue(tableToFind, out foundTable)) 
{ 
    builder.AppendLine() 
     .Append("Table=" + tableToFind + " exist in table list"); 

    string foundField; 
    if (foundTable.TryGetValue(fieldToFind, out foundField)) 
    { 
     builder.AppendLine() 
      .AppendFormat("Table={0}, Field={1} with value={2} exist in table list", 
       tableToFind, fieldToFind, foundField); 
    } 
} 
txtMessage.Text = builder.ToString(); 

嵌套的字典是不是不好的事情,這是一個很好的方式來組織鍵和值的層次結構。但爲了保持可維護性,您通常應該將所有內容封裝在另一個類中,以提供操作數據的方法,而無需直接管理字典。您可以使其既高效又可維護。如何實施這是一個留給你的練習。

2

我不認爲這麼多字典會「有效」。

我認爲最好的辦法是將值添加到字典一樣多次 - 假設你希望能夠索引根據indicies之一(不是全部)他們:

dictionary.Add("FField1", "xxx"); 
dictionary.Add("TTable1", "xxx"); 

否則使用如果要根據所有的指示將它們編入索引,則可以使用連接字符(如'\0')。

dictionary.Add("Table1\0Field1", "xxx"); 
+0

第一種方法有幾個問題。如果'FField1'存在於多個表中,則存在重複鍵的問題。此外,由於您的密鑰數量是原來的兩倍,因此您的字典的最大大小減半。不過,第二種選擇是構建一個組合鍵,這是一個很好的選擇。 –

+0

@Jim確實,雖然我無法弄清楚他想如何索引 - 所以我不得不提出兩個解決方案。 –

+0

@jonathan,jim。感謝您的回答。我會嘗試,如果第二個選項將是我想要做的更好的選擇。 基本上,我想要做的是創建一個可搜索的持有者來獲取選定的表,它們的字段和選定的自定義字段屬性列表 - 避免頻繁訪問數據庫。 –

4

您可以使用編譯器爲您創建組合鍵:使用匿名類型。

var dictionary = new Dictionary<Object, int>(); 

dictionary.Add(new{Text="A", Number=1}, 1); 
dictionary.Add(new{Text="A", Number=2}, 3); 
dictionary.Add(new{Text="B", Number=1}, 4); 
dictionary.Add(new{Text="B", Number=2}, 5); 

var x = dictionary[new{Text="B", Number=2}]; 

C#將根據您的字段實現Equals和GetHashcode。因此,您確實得到了一個將按照您的預期行事的關鍵。

+0

這很有趣。編譯器生成一個比較每個字段的「Equals」方法。我不知道它會這樣做。 –

+0

@robert。這確實很有趣。我也會試試這個。謝謝! OMG! –

+0

OMG!這就像多鍵詞典中的聖盃。你不會相信人們創造多鍵或基於陣列的關鍵字典的長度。謝謝!!!!!!!!!! – Harindaka

相關問題