C#字典添加:无法将“字符串”转换为“System.Collections.Specialized.NameValueCollection”。

7

我是一个有用的助手,可以为您进行翻译。以下是需要翻译的内容:

我有一个数据源,其中包含以下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"}
        };

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

我希望能够遍历整个源并将“名称”值保留为键,并将“Config”和“Value”存入“NameValueCollection”中。

为此,我使用了如下的字典:

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

但是,在添加到这个字典时,我遇到了两个问题:
foreach(var c in lst)
        {
            config.Add(c.Name, new NameValueCollection { c.Config, c.Value });
        }
  1. 重复的键 (名称="A")
  2. 这行代码出错了,new NameValueCollection { c.Config, c.Value });

注意 - 我想要对于 X 来说同时得到 1 和 2 (在键名重复的情况下)

是否有更好的 C# 集合或如何解决上述错误。

谢谢!


3
如果存在重复的键,您期望看到什么?X 的值为 1 和 2 都有吗?或者是最新的值?我们不知道。 - Sergey Berezovskiy
是的,对于X来说,1和2都是成立的。 - user584018
https://dev59.com/XGkw5IYBdhLWcg3wKXb_ - user5940189
我很好奇你想用这个NameValueCollection方法解决什么样的问题。看起来你的第一个数据结构(List<Configuration>)对于许多任务来说更好。 - Steve
我没有像 "List<Configuration>" 这样的直接数据,NameValueCollection 是用于其他一些目的(当我们有重复键 X 和其值为 1 和 2 时)。 - user584018
4个回答

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"]

但我认为 OP 想要使用 NameValueCollection 作为值。我也没有解释这种方法的问题在哪里。 - Tim Schmelter
@TimSchmelter 我认为OP是在问是否有更好的集合可供使用 :) - Sergey Berezovskiy
我忽略了这句话,但我猜他正在寻找一个“更好”的集合,因为有错误需要我们帮助修复。 - Tim Schmelter
@TimSchmelter 这个问题中有一个“或”连接词 - 是否有更好的C#集合或如何解决上述错误 :) 所以...我选择回答第一部分 - Sergey Berezovskiy

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 } });
            }
        }

很遗憾,这是低效的。如果您查找键,则字典非常高效。但是您使用从“Keys”属性返回的集合。此属性使用所有键填充集合。然后,“config.Keys.Contains(c.Name)”将此集合中的所有字符串与给定名称进行比较,这是“O(n)”操作。因此,您会失去字典的查找性能。相反,请使用“config.TryGetValue”。 - Tim Schmelter
谢谢@TimSchmelter!:) - Yashar Aliabbasi
你的 if 语句体是错误的,应该是:config[c.Name].Add(c.Config, c.Value);。但更好的方法是:使用 temp.Add(c.Config, c.Value) 来避免多次查找。 - Tim Schmelter

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);
}

TryGetValueContainsKey更高效吗?为什么不直接用if(!config.ContainsKey(c.Name)) - Chris Dunaway
因为如果您想要向NameValueCollection添加新项,您需要再次进行查找。 - Tim Schmelter

0
尝试这个: 在字典类中不需要检查值是否重复; 如果是第一次,将添加。 如果是第二次,将更新。
   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 } };

        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接