What is the best collection type to easily lookup values with multiple, identical keys?
我有如下文本文档,其中包含单个和多个变量:
1 2 3 4 5 6 7 |
我需要遍历此文本文档的行,并用这些变量填充一个集合,目前我使用的是字典:
1 | public Dictionary<string, string> VariableNamesAndValues { get; set; } |
但在上面的示例中,这对多个相同的键(如"note"和"todo")不起作用,因为键在字典中必须是唯一的。
什么是最好的集合,这样我不仅可以得到这样的单个值:
1 2 3 4 5 | string variableValue =""; if (VariableNamesAndValues.TryGetValue("title", out variableValue)) return variableValue; else return""; |
但我也可以这样得到多个值:
1 2 3 4 5 6 | //PSEUDO-CODE: List<string> variableValues = new List<string>(); if (VariableNamesAndValues.TryGetValues("note", out variableValues)) return variableValues; else return null; |
如果键和值是字符串,则使用NameValueCollection。它支持给定键的多个值。
它不是世界上最有效的收藏品。尤其是因为它是一个非泛型类,使用了大量的虚拟方法调用,而getValues方法将为其返回值分配数组。但是,除非您需要性能最好的集合,否则这无疑是最方便的集合,可以满足您的要求。
您可以创建一个键:字符串和值:字符串列表的字典
编辑1和2:如果您可以使用.NET 3.0或更高版本,我已经想到了更好的解决方案。下面是一个Linq示例(我在没有Visual Studio的情况下键入了它,因此我希望它能够编译;):
1 2 3 4 5 6 7 8 | string[] lines = File.ReadAllLines("content.txt"); string[] separator = {"::"}; var splitOptions = StringSplitOptions.RemoveEmptyEntries; var items = from line in lines let parts = line.Split(separator, splitOptions) group parts by parts[0] into partGroups select partGroups; |
上述示例的简短说明:
- 从字符串数组中的文件中获取所有行
- 定义一些拆分选项(以保持示例可读)
- 对于行数组中的每一行,将其拆分到":"
- 将拆分结果分组到第一个拆分部分(例如标题、说明、注释等)
- 将分组的项存储在items变量中
LINQ查询的结果是一个
您可以使用PowerCollections,它是一个开放源代码项目,具有解决问题的多部门数据结构。
这是一个如何使用它的示例。
注:乔恩·斯基特在回答这个问题时曾提出过这个建议。
您可以使用
1 2 3 | ILookup<string, string> lookup = lines.Select(line => line.Split(new string[] {"::" }) .ToLookup(arr => arr[0], arr => arr[1]); IEnumerable<string> notes = lookup["note"]; |
请注意,此集合是只读的
我不是首席专家,但我认为
或者某种类型的
1 2 3 4 5 6 7 8 | if(map.get(aKey) == null) { map.put(aKey, new ArrayList(){{add(aValue);}}); } else { map.put(aKey, map.get(aKey).add(anotherValue)); } |
或者类似的东西。(或者,最短路径:
1 |
我以前用
下面是如何模拟只获取一个值。
1 2 3 4 5 6 7 8 9 10 11 | public static bool TryGetValue(this Dictionary<string, HashSet<string>> map, string key, out string result) { var set = default(HashSet<string>); if (map.TryGetValue(key, out set)) { result = set.FirstOrDefault(); return result == default(string); } result = default(string); return false; } |