2017-04-26 55 views
7

我有一個包含類似下面3個不同的值的數據源,添加到C#詞典:無法從「串」到「System.Collections.Specialized.NameValueCollection」

List<Configuration> lst = new List<Configuration> 
     { 
      new Configuration{Name="A", Config="X", Value="1"}, 
      new Configuration{Name="A", Config="X", Value="2"}, 
      new Configuration{Name="B", Config="Y", Value="2"} 
     }; 

public class Configuration 
{ 
    public string Name { get; set; } 
    public string Config { get; set; } 
    public string Value { get; set; } 
} 

在這裏我要重複轉換並且希望將「名稱」值保留爲「KEY」,並將「配置」值「保存」到「NameValueCollection」中。

爲此,我正在採取類似下面的字典,

var config = new Dictionary<string, NameValueCollection>(); 

但同時加入到這個字典餘米的遭遇2個問題,

foreach(var c in lst) 
     { 
      config.Add(c.Name, new NameValueCollection { c.Config, c.Value }); 
     } 
  1. 重複鍵(名稱爲 「A」 )
  2. 這一行給出錯誤,新的NameValueCollection {c.Config,c.Value});

注 - 我想這兩個1和2 X(在重複鍵的情況下)

有沒有更好的C#集合或如何解決上述錯誤。

謝謝!

+3

你期望看到是否有重複鍵? X和X都是1和2?或者最新的價值?我們不知道 –

+0

是的,1和2都是X – user584018

+0

http://stackoverflow.com/questions/10089850/c-sharp-dictionary-how-to-add-multiple-values-for-single-key – Orangesandlemons

回答

3

試試這個:

 List<Configuration> lst = new List<Configuration> 
     { 
      new Configuration{Name="A", Config="X", Value="1"}, 
      new Configuration{Name="A", Config="X", Value="2"}, 
      new Configuration{Name="B", Config="Y", Value="2"} 
     }; 
     var config = new Dictionary<string, NameValueCollection>(); 
     NameValueCollection temp = new NameValueCollection(); 
     foreach (var c in lst) 
     { 
      if(config.TryGetValue(c.Name, out temp)){ 
       config[c.Name].Add(c.Config,c.Value); 
      } 
      else{ 
       config.Add(c.Name, new NameValueCollection { {c.Config,c.Value } }); 
      } 
     } 
+0

不幸的是,這是低效的。如果你查找關鍵字,字典是非常有效的。但是你使用'Keys'屬性返回的集合。該屬性使用所有密鑰填充集合。然後,'config.Keys.Contains(c.Name)'比較這個集合中的所有字符串和給定的名字'O(n)'。所以你失去了字典的查找性能。而是使用'config.TryGetValue' –

+0

謝謝@TimSchmelter! :) –

+0

你的'if'的主體是不正確的,它必須是:'config [c.Name] .Add(c.Config,c.Value);'。但更好的是:'temp.Add(c.Config,c.Value)'以避免另一次查找 –

2

一個NameValueCollection包含多個名稱和值,因爲它的集合。所以你不能用你的方式來原創。但是您可以使用它將所有重複的Name組合到同一個集合中。我會用Dictionary<k,v>.TryGetValue

var config = new Dictionary<string, NameValueCollection>(); 

foreach (Configuration c in lst) 
{ 
    NameValueCollection nvc; 
    if(!config.TryGetValue(c.Name, out nvc)) 
    { 
     nvc = new NameValueCollection(); 
     config.Add(c.Name, nvc); 
    } 
    nvc.Add(c.Config, c.Value); 
} 
+0

TryGetValue'比'ContainsKey'更有效嗎?爲什麼不只是'if(!config.ContainsKey(c.Name))'? –

+0

因爲如果要將新項目添加到NameValueCollection,則需要再次查找它。 –

6

你可以使用的字典lookups(它代表其中鍵映射到多個值的集合):

var config = lst.GroupBy(cfg => cfg.Name) 
       .ToDictionary(g => g.Key, 
           g => g.ToLookup(cfg => cfg.Config, cfg => cfg.Value)); 

配置的類型將是

Dictionary<string, ILookup<string, string>> 

存取值:

config["A"]["X"] // gives you IEnumerable<string> with values ["1","2"] 
+0

但我認爲OP想要使用'NameValueCollection'作爲值。我也錯過了解釋這種方法有什麼問題 –

+0

@TimSchmelter我認爲OP是問是否有更好的收集使用:) –

+0

我忽略了這句話,但我想他是在尋找一個「更好」的收集,因爲的錯誤,我們可以幫助修復 –

0

試試這個: 在Dictionary類中不需要檢查值是否重複;如果它的第一次將被添加。 如果是第二次,它將被更新。

List<Configuration> lst = new List<Configuration> 
    { 
     new Configuration{Name="A", Config="X", Value="1"}, 
     new Configuration{Name="A", Config="X", Value="2"}, 
     new Configuration{Name="B", Config="Y", Value="2"} 
    }; 
     var config = new Dictionary<string, NameValueCollection>(); 
     foreach (var c in lst) 
     { 
      config[c.Name] = new NameValueCollection { { c.Config, c.Value } }; 

     } 
+0

爲什麼你沒有嘗試這個?它會正常工作 –