C#Linq .ToDictionary()密钥已经存在

Ton*_*zzo 5 c# regex linq ini dictionary

最终编辑:我能够找到ini文件中的重复字段.谢谢大家的帮助!

我正在使用正则表达式来解析ini文件,使用LINQ将其存储在Dictionary中:

示例数据:
[WindowSettings]
窗口X Pos ='0'
窗口Y Pos ='0'
窗口最大化='false'
窗口名称='Jabberwocky'

[记录]
目录='C:\ Rosetta Stone\Logs'

编辑:这是实际导致问题的文件:http://pastebin.com/mQSrkrcP

EDIT2:我把它缩小到由文件的最后一部分引起:[list_first_nonprintable]

由于某种原因,我正在解析的文件之一是抛出此异常:

System.ArgumentException:已添加具有相同键的项.

有没有办法让我找出导致问题的键(所以我可以修复文件),或者只是跳过导致这个问题的键并继续解析?

这是代码:

try
{
    // Read content of ini file.
    string data = System.IO.File.ReadAllText(project);

    // Create regular expression to parse ini file.
    string pattern = @"^((?:\[)(?<Section>[^\]]*)(?:\])(?:[\r\n]{0,}|\Z))((?!\[)(?<Key>[^=]*?)(?:=)(?<Value>[^\r\n]*)(?:[\r\n]{0,4}))*";
    //pattern = @"
    //^                           # Beginning of the line
    //((?:\[)                     # Section Start
    //     (?<Section>[^\]]*)     # Actual Section text into Section Group
    // (?:\])                     # Section End then EOL/EOB
    // (?:[\r\n]{0,}|\Z))         # Match but don't capture the CRLF or EOB
    // (                          # Begin capture groups (Key Value Pairs)
    //  (?!\[)                    # Stop capture groups if a [ is found; new section
    //  (?<Key>[^=]*?)            # Any text before the =, matched few as possible
    //  (?:=)                     # Get the = now
    //  (?<Value>[^\r\n]*)        # Get everything that is not an Line Changes
    //  (?:[\r\n]{0,4})           # MBDC \r\n
    //  )*                        # End Capture groups";

    // Parse each file into a Dictionary.
    Dictionary<string, Dictionary<string, string>> iniFile
                    = (from Match m in Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline)
                       select new
                       {
                           Section = m.Groups["Section"].Value,

                           kvps = (from cpKey in m.Groups["Key"].Captures.Cast<Capture>().Select((a, i) => new { a.Value, i })
                                   join cpValue in m.Groups["Value"].Captures.Cast<Capture>().Select((b, i) => new { b.Value, i }) on cpKey.i equals cpValue.i
                                   select new KeyValuePair<string, string>(cpKey.Value, cpValue.Value)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)

                       }).ToDictionary(itm => itm.Section, itm => itm.kvps);

    return iniFile;
}
catch (ArgumentException ex)
{
    System.Diagnostics.Debug.Write(ex.ToString());
    return new Dictionary<string, Dictionary<string, string>>();
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

McG*_*gle 10

这只是意味着当你转换为字典时 -

.ToDictionary(itm => itm.Section, itm => itm.kvps);
Run Code Online (Sandbox Code Playgroud)

- 有多个键(itm.Section).您可以使用ToLookup,它有点像字典但允许多个键.

编辑

有几种方法可以调用ToLookup.最简单的是指定键选择器:

var lookup = 
   // ...
.ToLookup(itm => itm.Section);
Run Code Online (Sandbox Code Playgroud)

这应该提供一个查找,其中键的类型为Group.获取查找值应返回IEnumerable,其中T是匿名类型:

Group g = null;
// TODO get group
var lookupvalues = lookup[g];
Run Code Online (Sandbox Code Playgroud)

如果.NET编译器不喜欢这样(有时它似乎无法弄清楚各种类型应该是什么),您还可以指定一个元素选择器,例如:

ILookup<string, KeyValuePair<string,string>> lookup = 
    // ...
.ToLookup(
    itm => itm.Section.Value,    // key selector
    itm => itm.kvps              // element selector
);
Run Code Online (Sandbox Code Playgroud)

  • 然后他可以使用LinqPad并调用.Dump()来查看数据. (2认同)