C# 林克 .ToDictionary() 键已存在
本文关键字:存在 林克 ToDictionary | 更新日期: 2023-09-27 18:34:19
最终编辑:我能够在ini文件中找到重复的字段。谢谢大家的帮助!
我正在使用正则表达式来解析 ini 文件,并使用 LINQ 将其存储在字典中:
示例数据:
[窗口设置]
窗口 x 位置='0'
窗口 Y 位置='0'
窗口最大化='假'
窗口名称='Jabberwocky'
[日志记录]
目录='C:''罗塞塔石碑''日志'
编辑:这是实际导致问题的文件:http://pastebin.com/mQSrkrcP
编辑2:我已将其缩小为由文件中的最后一部分引起:[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>>();
}
提前谢谢。
这只是意味着当你转换为字典时——
.ToDictionary(itm => itm.Section, itm => itm.kvps);
-- 有多个键(ITM.节(。 你可以改用ToLookup,它有点像字典,但允许多个键。
编辑
有几种方法可以调用 ToLookup。 最简单的方法是指定键选择器:
var lookup =
// ...
.ToLookup(itm => itm.Section);
这应该提供键类型为组的查找。 获取查找值应返回 IEnumerable,其中 T 是匿名类型:
Group g = null;
// TODO get group
var lookupvalues = lookup[g];
如果 .NET 编译器不喜欢这样(有时它似乎无法弄清楚各种类型应该是什么(,您还可以指定元素选择器,例如:
ILookup<string, KeyValuePair<string,string>> lookup =
// ...
.ToLookup(
itm => itm.Section.Value, // key selector
itm => itm.kvps // element selector
);
您可以编写自己的ToDictionary方法,该方法不会轻易中断重复键。
public static Dictionary<K,V> ToDictionary<TSource, K, V>(
this IEnumerable<TSource> source,
Func<TSource, K> keySelector,
Funct<TSource, V> valueSelector)
{
//TODO validate inputs for null arguments.
Dictionary<K,V> output = new Dictionary<K,V>();
foreach(TSource item in source)
{
//overwrites previous values
output[keySelector(item)] = valueSelector(item);
//ignores future duplicates, comment above and
//uncomment below to change behavior
//K key = keySelector(item);
//if(!output.ContainsKey(key))
//{
//output.Add(key, valueSelector(item));
//}
}
return output;
}
我假设您可以弄清楚如何实现额外的重载(没有选择器的值(。
Tuple
传递多个密钥。检查下面的示例代码:
.ToDictionary(k => new Tuple<string,string>(k.key1,k.key2), v => v.value)