【问题标题】:How to swap map elements如何交换地图元素
【发布时间】:2010-11-20 09:02:17
【问题描述】:

在 C++ 中,我如何交换 map 的两个元素?

【问题讨论】:

    标签: c++ stl map swap


    【解决方案1】:

    提供的答案是正确的,但对相同的键使用了两次operator[],这不是免费的,可以避免:

    std::map<char, std::string> a;
    

    解决方案 1:

    std::string &item1 = a['a'];
    std::string &item2 = a['b'];
    std::swap(item1, item2);
    

    解决方案 2:

    const std::map<char, std::string>::iterator item1 = a.find('a');
    const std::map<char, std::string>::iterator item2 = a.find('b');
    if ((item1 != a.end()) && (item2 != a.end()))
        std::swap(item1->second, item2->second);
    

    当然,这两个解决方案是不等价的(解决方案 2 仅交换映射中已经存在的值,解决方案 1 不加疑问地插入,最终可能交换两个默认构造的字符串)。

    【讨论】:

    • 解决方案 1 安全吗?我在 STL 文档中找不到任何内容可以说明对映射中值的引用不会因插入而失效,尽管在 g++ 中似乎没问题。
    • @Pete 我认为是,23.1.2/8 “插入成员不应影响迭代器的有效性和对容器的引用”
    【解决方案2】:

    我觉得std::swap()是个不错的选择。

    【讨论】:

    • 不幸的是std::map&lt;T&gt;::iterator 是一个常量迭代器,阻止用户在类外修改排序顺序。你必须先用const_cast 抛弃const-ness 才能执行std::swap
    【解决方案3】:

    到目前为止,提供的答案都没有处理不存在的键并保留这些键的不存在。

    template<class Key, class Value>
    void swap_map_elements(std::map<Key, Value>& map, const Key& key1, const Key& key2)
    {
        auto it1 = map.find(key1);
        auto it2 = map.find(key2);
        auto end = map.end();
    
        if(it1 != end && it2 != end) {
            std::swap(it1->second, it2->second);
        }
        else if(it1 != end) {
            map.emplace(std::make_pair(key2, std::move(it1->second)));
            map.erase(key1);
        }
        else if(it2 != end) {
            map.emplace(std::make_pair(key1, std::move(it2->second)));
            map.erase(key2);
        }
    }
    

    例子:

    auto M = std::map<int, std::string>();
    M.emplace(std::make_pair(1, "one"));
    M.emplace(std::make_pair(2, "two"));
    
    swap_map_elements(M, 1, 2); // 1: "two", 2: "one"
    swap_map_elements(M, 1, 4); // 2: "one", 4: "two"
    swap_map_elements(M, 5, 2); // 4: "two", 5: "one"
    swap_map_elements(M, 8, 9); // 4: "two", 5: "one"
    

    【讨论】:

      【解决方案4】:
        auto mymap = std::map<int, char>{{1, 'a'}, {2, 'b'}};
        std::swap(mymap.at(1), mymap.at(2));
      

      【讨论】:

        【解决方案5】:

        在地图中交换是什么意思?普通的普通原版地图没有任何特定的顺序,所以说到交换,就顺序而言没有任何意义。

        如果您正在寻找保留顺序的 C++ 映射实现,在这种情况下排序变得有意义,请查看 here

        但是,如果您希望将与一个键关联的值与与第二个键关联的值交换,那么就这样做

          map<char,string> mymap;
        
          mymap['a']="firstValue";
          mymap['b']="SecondValue";
          /*now let's swap*/
          string tmpString = mymap['a'];
          mymap['a']=mymap['b'];
          mymap['b']= tmpString
        

        【讨论】:

        • 啊,是的,我忘记了地图并没有真正的订单...感谢您指出这一点!
        • std::map 确实保持了排序顺序,这就是它被实现为自平衡二叉搜索树的原因。您可能会将其与 std::unordered_map 混淆,后者基本上是一个哈希映射 - 没有任何特定顺序。
        【解决方案6】:

        你是这个意思吗?

        const T tmp = map["a"];
        map["a"] = map["b"];
        map["b"] = tmp;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-11-06
          • 2020-06-10
          • 2019-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多