如何在保留顺序的前提下去除C++ std::vector<std::string>中的重复元素?
去除std::vectorstd::string重复元素并保留原顺序的最简方法
嘿,这个需求太常见了!既要去重又要保住原有元素的顺序,直接用std::set或者std::unordered_set存一遍肯定不行——它们会自动排序或者打乱顺序。这里给你两种实用的方案,看你需求选:
方法一:创建新容器(兼容所有C++版本)
这种方法兼容性拉满,不管是C11还是更早(当然C11起用unordered_set效率更高),思路就是用一个哈希集合记录已经见过的元素,遍历原容器时只把没出现过的元素加入新容器:
#include <vector> #include <string> #include <unordered_set> std::vector<std::string> removeDuplicates(const std::vector<std::string>& input) { std::vector<std::string> result; std::unordered_set<std::string> seen; for (const auto& str : input) { // 如果元素没出现过,就加入结果和已见集合 if (seen.insert(str).second) { result.push_back(str); } } return result; } // 测试你的示例 int main() { std::vector<std::string> container; container.push_back("z"); container.push_back("y"); container.push_back("x"); container.push_back("z"); auto unique_container = removeDuplicates(container); // 此时unique_container的元素就是 z, y, x return 0; }
这里seen.insert(str).second会返回一个bool值,表示这个元素是不是第一次被插入到集合里——如果是,就说明之前没见过,直接加到结果里就行。
方法二:原地修改(C++20及以上可用)
如果你不想额外创建新容器,想直接在原vector上修改,C++20新增的std::erase_if可以帮你实现更简洁的写法:
#include <vector> #include <string> #include <unordered_set> #include <algorithm> // 要包含这个头文件用erase_if void removeDuplicatesInPlace(std::vector<std::string>& input) { std::unordered_set<std::string> seen; std::erase_if(input, [&seen](const std::string& str) { // 如果元素已经见过,就返回true表示要删除;否则加入集合返回false if (!seen.insert(str).second) { return true; } return false; }); } // 测试示例 int main() { std::vector<std::string> container; container.push_back("z"); container.push_back("y"); container.push_back("x"); container.push_back("z"); removeDuplicatesInPlace(container); // 原container现在就是 z, y, x return 0; }
这种方法不需要额外的结果容器,直接在原容器上删除重复元素,代码更紧凑,但需要你的编译器支持C++20标准。
小提示
- 如果你需要对自定义类型去重,只要给类型提供合适的哈希函数(用
unordered_set的话)或者比较运算符就行,思路是一样的。 - 如果对性能要求极高,
unordered_set的哈希冲突可能会有影响,这时候可以考虑用std::set代替,但set是基于红黑树的,查找插入是O(logn),比unordered_set的平均O(1)慢一点。
内容的提问来源于stack exchange,提问作者jean553
相关产品推荐
相关产品推荐

