【问题标题】:How to work with dictionaries when I want to add new item?当我想添加新项目时如何使用字典?
【发布时间】:2017-06-07 07:05:32
【问题描述】:

当我使用哈希集时,我可以尝试添加一个新项目,如果该项目存在,则无关紧要。 hashset 不会抛出异常,只是继续。

使用字典,如果我想添加一个新项目,如果键存在,它会抛出异常。目前我总是这样做:

Dictionary<long, List<string>> myDic = new Dictionary<long, List<string>>();
long myNewKey = 1;
if(myDic.ConatainsKey(1) == false)
{
    myDic.Add(1, new List<string>());
}
myDic[myNewKey].Add("string01");
myDic[myNewKey].Add("string02");

当我想向字典添加新值时,它会让我随时重复许多代码。 这让我想知道是否有更好的方法来使用字典。

我也在想我可以创建一个扩展方法,但我想知道是否有更好的选择。

【问题讨论】:

标签: c# .net dictionary


【解决方案1】:

取决于字典值的类型(如键值)。在您的示例中,带有指向字符串列表的长键,真正的问题是需要创建一个新的对象值。如果 Dictionary 是指向值类型(例如:long->long)的值类型(如值与引用类型),则可以只使用索引器“[x]”。如果您知道键的范围,您可以提前初始化您的值对象。如果您只是想减少代码,您可以使用扩展方法来组合检查、添加对象和设置。像这样的:

public static class Extensions {
    public static void AppendToValues(this Dictionary<long, List<string>> dict, long key, string str){
        if (dict.ContainsKey(key)) {
            dict.Add(key, new List<string>());
            }
        dict[key].Add(str);
        }
    }   

然后在你的代码中这样调用它:

myDic.AppendToValues(myNewKey, "string01");

【讨论】:

    【解决方案2】:

    Dictionary&lt;TKey,TValue&gt; 有两种不同的添加项目的方式。

    void Add(TKey key, TValue value):因为您正在调用Add,所以您所说的语义是“这不存在,让它存在”。所以在重复插入时会引发异常,因为它不知道你想要旧的东西还是新的东西。

    索引器 (TValue this[TKey key]) 支持赋值,其语义为“如果我调用索引器 getter,我希望这是答案”。

    dict.Add(1, 1);
    var x = dict[1]; // x == 1
    dict.Add(1, 2); // throws
    
    dict.Add(1, 1);
    var x = dict[1]; // x == 1;
    dict[1] = 2;
    var y = dict[1]; // x == 1, y == 2.
    
    var dict = new Dictionary<long, int>();
    dict[1] = 35;
    var x = dict[1]; // x == 35;
    

    ContainsKey 几乎总是打错电话。如果您正在安全地读取该值,请调用TryGetValue,如果您只想使用字典来存储是否已完成某事,请使用HashSet&lt;T&gt;。 (谁的Add 方法返回一个booltrue 如果 Add 添加了一些东西(它不存在),false 如果 Add 没有工作(该值已经存在))。

    在您想要将内容添加到列表的特定情况下,TryGetValue 方法是最好的。或者,使用 ConcurrentDictionary:

    TryGetValue:

    List<string> list;
    
    // Read the dictionary exactly once
    if (!dict.TryGetValue(key, out list))
    {
        list = new List<string>();
        // Write at most once.
        dict[key] = list;
    }
    
    list.Add(value);
    

    并发字典:

    ConcurrentDictionary<long, List<string>> dict = new ConcurrentDictionary<long, List<string>>();
    ...
    List<string> list = dict.GetOrAdd(key, () => new List<string>());
    list.Add(value);
    

    【讨论】:

      【解决方案3】:

      如果没有扩展方法(或 Dictionary 子类,顺便说一句,这有点过头了),我认为你无法实现你想要的。

      您可以在这里找到使用 Dictionary.TryGetValue 的扩展方法的一个很好的实现(如果找不到键,它不会抛出异常):

      Dictionary returning a default value if the key does not exist

      如果您仍然不想使用扩展方法,TryGetValue 将提供更好的性能,因为键的查找只完成一次:

      Dictionary<long, List<string>> myDic = new Dictionary<long, List<string>>();
      long myNewKey = 1;
      List<string> list;
      if (!myDic.TryGetValue(myNewKey, out list))
      {
          list = new List<string>();
          myDic.Add(myNewKey, list);
      }
      
      list.Add("string01");
      list.Add("string02");
      

      【讨论】:

        猜你喜欢
        • 2012-06-17
        • 2016-02-21
        • 2014-09-14
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 2016-08-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多