You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何遍历std::map并将满足断言的键值对移至另一个std::map

拆分std::map到另一个map的高效实现

一、基于键范围的断言(最高效)

如果你的断言可以转化为键的连续范围(比如键大于等于X、小于Y),直接利用std::map的有序特性,结合extract和merge操作,这是最优方案——完全不需要拷贝或移动元素,仅转移节点所有权:

#include <map>
#include <string>

int main() {
    std::map<int, std::string> m = {{1, "a"}, {5, "e"}, {7, "g"}, {10, "j"}};
    std::map<int, std::string> m2;

    // 自定义断言:键 >=5 且键 <10
    auto start = m.lower_bound(5);
    auto end = m.upper_bound(9);

    // 提取该范围的节点并合并到m2
    m2.merge(m.extract(start, end));
}

复杂度:O(log n + k),k为移动的元素数量,几乎无额外开销

二、任意自定义断言(值/键值组合判断)

如果断言是任意条件(比如值的长度、内容,或键值的组合判断),可以用extract逐个处理满足条件的元素,避免拷贝开销:

#include <map>
#include <string>

int main() {
    std::map<int, std::string> m = {{1, "a"}, {2, "bb"}, {3, "c"}, {4, "ddd"}};
    std::map<int, std::string> m2;

    auto it = m.begin();
    while (it != m.end()) {
        // 自定义断言:值的长度大于1
        if (it->second.size() > 1) {
            // 先递增迭代器,再提取节点(extract会使当前迭代器失效)
            m2.insert(m.extract(it++));
        } else {
            ++it;
        }
    }
}

注意:extract是C++17引入的特性,确保编译器支持该标准

兼容C++11/14的替代方案

如果无法使用C++17,可通过std::move转移元素,再从原map中删除:

#include <map>
#include <string>
#include <utility>

int main() {
    std::map<int, std::string> m = {{1, "a"}, {2, "bb"}, {3, "c"}, {4, "ddd"}};
    std::map<int, std::string> m2;

    auto it = m.begin();
    while (it != m.end()) {
        if (it->second.size() > 1) {
            // 移动元素到m2,再删除原位置元素
            m2.insert(std::move(*it));
            it = m.erase(it);
        } else {
            ++it;
        }
    }
}

该方案会触发元素的移动构造,效率略低于extract,但远优于拷贝

关键说明

  • 避免直接遍历拷贝后erase:这种方式会产生不必要的元素拷贝,对于大容器或大类型(如长字符串),性能损耗明显。
  • extract和merge操作仅转移节点所有权,不涉及元素的构造/析构,是处理大容器的最优选择。

内容的提问来源于stack exchange,提问作者calvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:55:11