将字符串集合转换为字典

时间:2012-05-17 01:24:17

标签: c# linq

这可能是一个简单的问题,但答案是在逃避我。

我有一个字符串集合,我正在尝试将其转换为字典。

集合中的每个字符串都是我从正则表达式匹配中获得的以逗号分隔的值列表。我希望字典中每个条目的键是逗号分隔列表中的第四个元素,相应的值是逗号分隔列表中的第二个元素。

当我尝试直接调用ToDictionary时,我最终会出现某种循环,这似乎让我对我所在的BackgroundWorker线程感兴趣:

var MoveFromItems = matches.Cast<Match>()
                           .SelectMany(m => m.Groups["args"].Captures
                           .Cast<Capture>().Select(c => c.Value));

var dictionary1 = MoveFromItems.ToDictionary(s => s.Split(',')[3], 
                                             s => s.Split(',')[1]);

当我手动创建字典时,一切正常:

var MoveFroms = new Dictionary<string, string>();

foreach(string sItem in MoveFromItems) 
{
    string sKey = sItem.Split(',')[3]; 
    string sVal = sItem.Split(',')[1];

    if(!MoveFroms.ContainsKey(sKey))
        MoveFroms[sKey.ToUpper()] = sVal;
}

感谢您提供的任何帮助。

3 个答案:

答案 0 :(得分:3)

问题很可能是密钥有重复。你有三个选择。

保留首次参赛作品 (这是您目前在foreach循环中所做的事情)

键只有一个条目,第一个条目出现 - 意味着您可以拥有Dictionary

var first = MoveFromItems.Select(x => x.Split(','))
                         .GroupBy(x => x[3])
                         .ToDictionary(x => x.Key, x => x.First()[1]);

保留所有条目,分组

密钥将包含多个条目(每个密钥返回Enumerable),并使用Lookup代替Dictionary

var lookup = MoveFromItems.Select(x => x.Split(','))
                          .ToLookup(x => x[3], x => x[1]);

保留所有条目,展平

没有钥匙,只是一个扁平的条目列表:

var flat = MoveFromItems.Select(x => x.Split(','))
                        .Select(x => new KeyValuePair<string,string>(x[3], x[1]));

你也可以在这里使用元组(Tuple.Create(x[3], x[1]);)。


注意:在这些情况下,您需要决定在何种情况下/您希望密钥是大写还是小写。我还没有做过任何相关的事情。如果您想将密钥存储为大写,只需在上面的所有内容中将x[3]更改为x[3].ToUpper()

答案 1 :(得分:1)

这将Split MoveFromItems','的每个字符串var dict = MoveFromItems.Select(x => x.Split(',')) .ToLookup(x => x[3], x => x[1]); ,并将第4项(第3个索引)作为键,第2项(第1个索引)作为值。

{{1}}

答案 2 :(得分:1)

这会分割每个项目,并从第4个分割值中选择键,并从第2个分割值中选择值,全部放入字典中。

var dictionary = MoveFromItems.Select(s => s.Split(','))
                              .ToDictionary(split => split[3],
                                            split => split[1]);

将字符串拆分两次没有意义,只是为了使用不同的索引。

这就像将拆分结果保存到局部变量,然后使用它来访问索引3和1一样。

但是,如果确实你不知道密钥是否会再次出现,我会毫不怀疑地采用你已经实现的简单循环。

虽然你的循环中有一个小错误:

MoveFroms = new Dictionary<string, string>();

foreach(string sItem in MoveFromItems) 
{
    string sKey = sItem.Split(',')[3]; 
    string sVal = sItem.Split(',')[1];

    // sKey might not exist as a key
    if (!MoveFroms.ContainsKey(sKey))
    //if (!MoveFroms.ContainsKey(sKey.ToUpper()))
    {
        // but sKey.ToUpper() might exist!
        MoveFroms[sKey.ToUpper()] = sVal;     
    }
}

如果你真的想要关键所有大写的话,你的病情也应该ContainsKey(sKey.ToUpper())