代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

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

  •  8
  • Edward Tanguay  · 技术社区  · 15 年前

    我有 文本 如下文件包含 单一的 倍数 变量:

    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 回复  |  直到 15 年前
        1
  •  7
  •   Josh    15 年前

    如果键和值是字符串,则使用 NameValueCollection . 它支持给定键的多个值。

    这不是世界上最有效的收藏品。特别是因为它是一个非泛型类,使用了很多虚拟方法调用,而getvalues方法将为其返回值分配数组。但除非你需要最好的 表演 收藏,这当然是最 方便的 按你的要求收集。

        2
  •  3
  •   Yvo    15 年前

    你可以编一本字典 关键: 字符串和 价值观: 字符串列表

    Dictionary<string,List<string>>

    编辑1&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;
    

    对上述示例的简要说明:

    • 获取字符串数组中文件的所有行
    • 定义一些拆分选项(保持示例可读)
    • 对于Lines数组中的每一行,将其拆分为:
    • 对第一个拆分部分的拆分结果进行分组(例如标题、说明、注释等)
    • 将分组的项存储在items变量中

    linq查询的结果是 IQueryable<IGrouping<string, IEnumberable<string>>> .
    结果中的每个项目都有一个 Key 包含行的键(标题、说明、注释…)的属性。
    可以枚举包含所有值的每个项。

        3
  •  2
  •   Thomas Levesque    15 年前

    你可以用一个 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"];
    

    请注意,此集合是只读的

        4
  •  2
  •   Community CDub    8 年前

    您可以使用 PowerCollections 这是一个开源项目,它有一个多字典的数据结构,可以解决您的问题。

    这里是一个 sample of how to use it .

    注:Jon Skeet以前在回答 this question.

        5
  •  1
  •   Tedil    15 年前

    我不是专家,但我想 Dictionary<string, List<string>>

    或者某种 HashMap<string, List<string>> 可能工作。 例如(Java伪代码): 阿基瓦尔 其他价值

    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);}});
    
        6
  •  1
  •   ChaosPandion    15 年前

    我已经用过 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;
    }