使用多个相同的键轻松查找值的最佳集合类型是什么?

时间:2010-03-06 18:33:05

标签: c# collections dictionary

我的文字文档如下所示,其中包含单个多个变量:

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;

6 个答案:

答案 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;

上述例子的简短说明:

  • 从String数组中获取文件中的所有行
  • 定义一些拆分选项(以保持示例可读)
  • 对于lines数组中的每一行,将其拆分为“::”
  • 将拆分结果分组到第一个拆分部分(例如标题,说明,注释......)
  • 将分组的项目存储在项目变量

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数据结构的开源项目,可以解决您的问题。

这是sample of how to use it

注意: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);}});