【问题标题】:How to update std::map after using the find method?使用 find 方法后如何更新 std::map ?
【发布时间】:2011-05-30 11:40:06
【问题描述】:

使用find方法后如何更新std::map中某个key的值?

我有一个这样的映射和迭代器声明:

map <char, int> m1;
map <char, int>::iterator m1_it;
typedef pair <char, int> count_pair;

我正在使用地图来存储一个字符的出现次数。

我正在使用 Visual C++ 2010。

【问题讨论】:

    标签: c++ map stl stdmap


    【解决方案1】:

    std::map::find 将迭代器返回到找到的元素(如果未找到元素,则返回到 end())。只要map不是const,就可以修改迭代器指向的元素:

    std::map<char, int> m;
    m.insert(std::make_pair('c', 0));  // c is for cookie
    
    std::map<char, int>::iterator it = m.find('c'); 
    if (it != m.end())
        it->second = 42;
    

    【讨论】:

    • 谢谢。是否也可以使用 [] 运算符?
    • @Jay:是的,但行为不同。 map提供的各种功能见the map documentation
    • 我收到了error: assignment of member 'std::pair&lt;char* const, char*&gt;::second' in read-only object :(
    • @jaykumarark 我认为是的,但这个解决方案的缺点是,地图必须第二次找到项目的位置(第一次是你调用 find 方法),这是具有 log(N) 复杂性的操作。这是不必要的相同操作的重复。
    【解决方案2】:

    我会使用运算符[]。

    map <char, int> m1;
    
    m1['G'] ++;  // If the element 'G' does not exist then it is created and 
                 // initialized to zero. A reference to the internal value
                 // is returned. so that the ++ operator can be applied.
    
    // If 'G' did not exist it now exist and is 1.
    // If 'G' had a value of 'n' it now has a value of 'n+1'
    

    因此,使用这种技术,从流中读取所有字符并计算它们变得非常容易:

    map <char, int>                m1;
    std::ifstream                  file("Plop");
    std::istreambuf_iterator<char> end;
    
    for(std::istreambuf_iterator<char> loop(file); loop != end; ++loop)
    {
        ++m1[*loop]; // prefer prefix increment out of habbit
    }
    

    【讨论】:

    • 您的回答非常适合实际问题——遗憾的是,提问者没有以明显的方式提出(因此接受)这个问题。这就是为什么我认为对这个事实做一个简短的陈述会更好:“阅读”非常快的人可能会相信你在使用find之后建议使用[](我不认为这是你的意图)。
    • 好吧,我认为如果不想隐式插入一个元素,'find' 会更好。通过 SIGSEGV 取消引用“查找”和死亡可能是可取的。
    • @GwangmuLee 取消引用 end() 迭代器是未定义的行为,它不需要生成 SIGSEGV(根据我的经验,不太可能这样做)。
    【解决方案3】:

    你可以使用std::map::at成员函数,它返回一个对key k标识的元素的映射值的引用。

    std::map<char,int> mymap = {
                                   { 'a', 0 },
                                   { 'b', 0 },
                               };
    
      mymap.at('a') = 10;
      mymap.at('b') = 20;
    

    【讨论】:

      【解决方案4】:

      你可以像下面这样更新值

         auto itr = m.find('ch'); 
           if (itr != m.end()){
                 (*itr).second = 98;
           }
      

      【讨论】:

        【解决方案5】:

        你也可以这样做-

         std::map<char, int>::iterator it = m.find('c'); 
         if (it != m.end())
         (*it).second = 42;
        

        【讨论】:

          【解决方案6】:

          如果您已经知道密钥,则可以使用m[key] = new_value 直接更新该密钥处的值

          这是一个可能有帮助的示例代码:

          map<int, int> m;
          
          for(int i=0; i<5; i++)
              m[i] = i;
          
          for(auto it=m.begin(); it!=m.end(); it++)
              cout<<it->second<<" ";
          //Output: 0 1 2 3 4
          
          m[4] = 7;  //updating value at key 4 here
          
          cout<<"\n"; //Change line
          
          for(auto it=m.begin(); it!=m.end(); it++)
              cout<<it->second<<" ";
          // Output: 0 1 2 3 7    
          

          【讨论】:

          • 除非您想要做的 only 事情是更新值,并且您已经确定密钥存在(或者您不在乎是否有新密钥创建),您不想使用此策略。一种狭窄的应用程序。在几乎所有情况下,您最好先执行 map::find(),获取迭代器并更新 iterator->second,正如其他答案所建议的那样。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-18
          • 2012-02-05
          • 2019-12-02
          • 2021-11-12
          相关资源
          最近更新 更多