【问题标题】:Copying C++ Map into key and value vectors将 C++ Map 复制到键和值向量中
【发布时间】:2012-04-12 02:37:02
【问题描述】:

我有一个 map,我希望将第一列 i.e (*it).first 推回到一个向量中,然后将 (*it)->second 推回到另一个向量中

这是最好的方法吗?

std::vector<std::string>test;
for ( it=mymap.begin() ; it != mymap.end(); it++ )
{
    test.push_back((*it).first);
}

我的另一个问题是我是否有一个循环,即 我如何将所有整数 i 插入到 (*it).first 中?

for(int i = 0; i < 10; i++)
{
    // 1 - 10 will go in (*it).first
}

我想在(*it).first 中有一些整数,并在(*it).second; 中有关联的值

【问题讨论】:

  • 你能澄清一下你在问什么吗?
  • 您的“其他问题”不清楚。
  • 更多信息现已添加

标签: c++ vector map


【解决方案1】:

我的另一个问题是我是否有一个循环,即如何插入所有 整数 i 成 (*it).first?

std::map 的情况下,您不能像那样修改返回的迭代器...std::map 键/值对数据结构中的键成员(即第一个)被有意指定为一个常量值,并在 std::map 数据结构中的键/值对生命周期开始时初始化为其常量值。如果键不是恒定的,则在更改键时最终会造成严重破坏,因为std::map 中的节点假定按键排序。键/值对数据结构的第二个成员是可以更改的成员。

因此,如果您想在映射中插入一组键/值对,您只需执行以下操作:

std::map<int, int> mymap;
int some_other_value = 100;

for (int i=0; i < 10; i++)
{
    mymap[i] = some_other_value++;
}

【讨论】:

    【解决方案2】:

    假设您已将映射声明为字符串键和值(即map&lt;string, string&gt; mymap;,那么它将如下所示,还假设您已将“it”变量声明为map&lt;string, string&gt;::iterator it,等等:

    std::vector<std::string> test;
    std::vector<std::string> second;
    std::map<string, string>::iterator it;
    
    for ( it=mymap.begin() ; it != mymap.end(); it++ )
    {
        test.push_back((*it).first);
        second.push_back((*it).second);
    }
    

    不确定您的下一个问题。

    【讨论】:

    • 使用 foreach 结构会更好:不必在每次迭代时重新计算 mymap.end()
    【解决方案3】:

    你问题的第一部分:

    std::vector<std::string> test;
    std::vector<std::string> test2; // assuming map is from string to string
    for (it = mymap.begin(); it != mymap.end(); ++it)
    {
       test.push_back(it->first);     // push first in one vector
       test2.push_back(it->second);   // push second in another vector
    }
    

    所以,是的,一个简单的 for 可以做你想做的事。


    你问题的第二部分:

    由于您正在更新地图的密钥,因此您需要将其从地图中移除并插入更改后的密钥。所以:

    std::string first, second;
    first = it->first;
    second = it->second;
    mymap.erase(it);        // be careful with invalidating iterator
    // change first
    mymap[first] = second;
    

    要通过将所有整数 i 添加到 first 来更改 first,这实际上取决于 first 的类型。例如对于一个字符串,你可能的意思是这样的:

    ostringstream sout;
    for (int i = 0; i < 10; ++i)
        sout << (i?" ":"") << i;
    first = sout.str();
    

    或者如果 first 是 set,你可能是这样的:

    for (int i = 0; i < 10; ++i)
        first.insert(i);
    

    【讨论】:

      【解决方案4】:

      您的第一个问题“如何将地图的第一列推入一个向量,将第二列推入另一个向量”这样解决了:

      std::map<std::string, std::string> mymap;
      std::vector<std::string> keys;
      std::vector<std::string> values;
      for ( std::map<std::string,std::string>::iterator it=mymap.begin() ; it != mymap.end(); ++it )
      {
        keys.push_back(it->first);
        values.push_back(it->second);
      }
      

      您的第二个问题,“如何将所有整数 i 插入 (*it).first ?”这样就解决了:

      std::map<int, int> mymap2;
      for(int i = 0; i < 10; i++)
      {
        // Insert default value into map
        // This sets '(*it).first' to 'i' and
        // '(*it).second' to a default value (in
        // this case, 0).
        mymap2[i];
      }
      

      std::map<int, int> mymap3;
      for(int i = 0; i < 10; i++)
      {
        // Insert specified value into map
        // this sets '(*it).first' to 'i', and
        // '(*it).second' to the value returned from the function.
        maymap3[i] = ChooseSpecificValue(i);
      }
      

      【讨论】:

      • 啊,好吧,对于 (*it).second 来说,这将是相同的 mymap[j[i] @Rob ?
      • std::map 数据结构不是二维数组,它们是所谓的关联数据结构,因此您不应该将键/值对之间的关​​系视为索引成一个数组。相反,(*it).second 是键/值对中的值。因此,换句话说,如果您在地图中搜索值 (*it).first,那么它将直接与 (*it).second 关联。
      • @ShamariCampbell 也许我添加到示例代码中的 cmets 让它更清晰。
      • @RemyLebeau - 你是对的。但是.insert() 将运行完全相同的搜索。事实上,在我的电脑上,operator[] 只不过是对insert() 的轻包装。在我的测试中,insert() 总是稍微快一点,但速度永远不会超过 20%。
      • @Robᵩ 你说得对,我忘记了insert() 将迭代器返回到现有元素,因此无论如何它都必须进行搜索。我可能正在考虑另一个容器。没关系。
      【解决方案5】:

      这里将是一个迭代器,它将指向 map 中的一个位置,并且一个迭代器最多有一个第一个和第二个值。根据键/值组合,您最多可以有多个键或相同的键持有相同/不同的值。

      至于在 map 中为键推送向量中的值时,您可以按照推送键的相同方式进行操作

           std::vector<std::string>test;
      
            std::vector<std::string>test2; 
      
            for ( it=mymap.begin() ; it != mymap.end(); it++ )
      
      
           {
      
             test.push_back((*it).first); 
      
            test2.push_back((*it).second);
      
      
           }
      

      你的问题很不清楚。

      【讨论】:

        【解决方案6】:

        如果您想在地图中处理不同的数据类型,我会模板化一个通用复制函数:

        template <class A, class B>
        void mycopy(std::map<A, B>&m, std::list<A>& keys, std::list<B>& values) {
            typename std::map<A, B>::iterator it;
            for (it = m.begin(); it != m.end(); ++it) {
                keys.push_back( (*it).first );
                values.push_back( (*it).second );   
            }
        
        }
        

        混合起来:

        std::map<int, std::string> mymap;
        std::list<int> keys;
        std::list<std::string> values;
        
        mymap[1] = "string1";
        mymap[2] = "string2";
        
        mycopy(mymap, keys, values);
        
        
        std::map<std::string, int> mymap1;
        std::list<std::string> keys1;
        std::list<int> values1;
        
        mymap1["string1"] = 1;
        mymap1["string2"] = 2;
        
        mycopy(mymap1, keys1, values1);
        

        编辑:是的 __copy 不是最好的定义。谢谢

        【讨论】:

        • 不要使用__copy:使用带有两个下划线的标识符是未定义的行为。
        【解决方案7】:

        嗯,可以通过一个简单的循环来完成:

        for (auto const& p: mymap) {
          vec1.push_back(p.first);
          vec2.push_back(p.second);
        }
        

        或者使用std::transform算法,虽然这里很冗长:

        std::transform(mymap.begin(), mymap.end(), std::back_inserter(vec1),
                       [](MyMap::const_reference p) { return p.first; });
        

        【讨论】:

          【解决方案8】:

          使用std::transform

          首先定义两个函数keyvalue,它们分别接受一对字符串并返回第一个或第二个值。

          #include <map>
          #include <vector>
          #include <algorithm>
          #include <iostream>
          #include <iterator>
          
          const std::string& key(const std::pair<std::string, std::string>& keyValue)
          {
              return keyValue.first;
          }
          
          const std::string& value(const std::pair<std::string, std::string>& keyValue)
          {
              return keyValue.second;
          }
          

          然后使用 &lt;algorithm&gt; 中的 std::transform 和函数将映射转换为键的 vector 或值的 vector

          int main()
          {
              using namespace std; // be explicit normally, trying to be brief here
          
              map<string, string> contacts;
          
              contacts["alice"] = "555-2701";
              contacts["bob"] = "555-2702";
          
              vector<string> keys(contacts.size());
              vector<string> values(contacts.size());
          
              transform(contacts.begin(), contacts.end(), keys.begin(), key);
              transform(contacts.begin(), contacts.end(), values.begin(), value);
          
              cout << "Keys:\n";
              copy(keys.begin(), keys.end(), ostream_iterator<string>(cout, "\n"));
          
              cout << "\n";
          
              cout << "Values:\n";
              copy(values.begin(), values.end(), ostream_iterator<string>(cout, "\n"));
          
              return 0;
          }
          

          输出:

          Keys:
          alice
          bob
          
          Values:
          555-2701
          555-2702
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-08-10
            • 2011-06-29
            • 1970-01-01
            • 2012-06-10
            • 1970-01-01
            相关资源
            最近更新 更多