我的文字文档如下所示,其中包含单个和多个变量:
title:: Report #3
description:: This is the description.
note:: more information is available from marketing
note:: time limit for this project is 18 hours
todo:: expand the outline
todo:: work on the introduction
todo:: lookup footnotes
我需要遍历此文本文档的行并使用这些变量填充集合,目前我正在使用词典:
public Dictionary<string, string> VariableNamesAndValues { get; set; }
但是这不适用于多个,相同的键,例如上面示例中的“note”和“todo”,因为键必须唯一在词典中。
什么是最好的收藏品,这样我才能获得这样的单一值:
string variableValue = "";
if (VariableNamesAndValues.TryGetValue("title", out variableValue))
return variableValue;
else
return "";
但我也可以像这样获得多个值:
//PSEUDO-CODE:
List<string> variableValues = new List<string>();
if (VariableNamesAndValues.TryGetValues("note", out variableValues))
return variableValues;
else
return null;
答案 0 :(得分:7)
如果你的键和值是字符串,那么使用NameValueCollection。它支持给定密钥的多个值。
它不是世界上最有效的收藏品。特别是因为它是一个非泛型类,使用了大量的虚方法调用,而GetValues方法将为其返回值分配数组。但除非您需要最好的执行集合,否则这肯定是最符合您要求的方便集合。
答案 1 :(得分:3)
您可以制作键字词典字符串和值:字符串列表
Dictionary<string,List<string>>
编辑1&amp; 2:强>
如果你可以使用.NET 3.0或更高版本,我想到了一个更好的解决方案
这是一个LINQ示例(我没有Visual Studio键入它,所以我希望它编译;)):
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;
上述例子的简短说明:
LINQ查询的结果是IQueryable<IGrouping<string, IEnumberable<string>>>
结果中的每个项目都有一个Key
属性,其中包含该行的键(标题,说明,注释......)。
可以枚举包含所有值的每个项目。
答案 2 :(得分:2)
您可以使用Lookup<TKey, TElement>
:
ILookup<string, string> lookup = lines.Select(line => line.Split(new string[] { ":: " })
.ToLookup(arr => arr[0], arr => arr[1]);
IEnumerable<string> notes = lookup["note"];
请注意,此集合是只读的
答案 3 :(得分:2)
您可以使用PowerCollections这是一个具有MultiDictionary数据结构的开源项目,可以解决您的问题。
注意:Jon Skeet在回答this question.
之前曾建议过答案 4 :(得分:1)
我过去曾使用Dictionary<string, HashSet<string>>
获取多个值。我很想知道是否有更好的东西。
以下是如何模拟只获取一个值的方法。
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;
}
答案 5 :(得分:1)
我不是c#专家,但我认为Dictionary<string, List<string>>
或某种HashMap<string, List<string>>
可能有用。
例如(Java伪代码):
aKey aValue
aKey anotherValue
if(map.get(aKey) == null)
{
map.put(aKey, new ArrayList(){{add(aValue);}});
}
else
{
map.put(aKey, map.get(aKey).add(anotherValue));
}
或类似的东西。 (或者,最短的方式:
map.put(aKey, map.get(aKey) != null ? map.get(aKey).add(value) : new ArrayList(){{add(value);}});