C++ vector结构体非连续去重及remove_if报错解决
问题根因
你遇到的编译错误和功能不生效问题来自两个核心错误:
- 谓词参数不匹配:
std::remove_if要求传入的判断逻辑是一元谓词,只接收单个遍历到的元素作为入参,返回布尔值标记该元素是否需要删除。你写的isEqual是需要传入两个元素做比较的二元谓词,是给std::unique这类两两比较的接口用的,参数个数不匹配直接触发编译报错。 - 接口选型错误:就算修正谓词格式,
std::remove_if本身不具备跨元素记录已出现内容的能力,原生逻辑无法识别非连续排布的重复项;另外你之前用std::unique只去连续重复的问题,本质是因为你仅按POS字段排序,相同POS下Record一致的重复项没有被排到连续位置,自然无法被unique识别。
另外你的相等判断逻辑本身也不符合业务规则:只比较了Record字段,没有校验POS是否一致,会把POS不同但Record恰好相同的合法记录误判为重复。
适配你场景的最优实现方案
你的vector已经按POS字段完成排序,所有相同POS的记录本身是连续聚集的,只需要在相同POS的分组内补充按Record排序,就能让所有符合重复定义(POS相同 + Record内容一致)的记录连续排布,之后直接用std::unique去重即可,性能远高于哈希表遍历去重的方案。
完整实现代码如下:
#include <vector> #include <algorithm> #include <cstring> // 你的Data结构体定义保持不变 typedef struct Data { char name[12]; int POS ; char Record[600]; }; // 排序规则:先按POS升序,POS相同则按Record字典序升序,保证重复记录连续 auto dataCmp = [](const Data& lhs, const Data& rhs) { if (lhs.POS != rhs.POS) { return lhs.POS < rhs.POS; } return strcmp(lhs.Record, rhs.Record) < 0; }; // 重复判定规则:POS相同 且 Record内容完全一致,才判定为重复记录 auto isDuplicate = [](const Data& lhs, const Data& rhs) { if (lhs.POS != rhs.POS) { return false; } return strcmp(lhs.Record, rhs.Record) == 0; }; // 替换你原来问题代码行的逻辑 // 因为你之前已经按POS排过序,本次排序仅调整同POS下的Record顺序,开销极低 std::sort(sortedV.begin(), sortedV.end(), dataCmp); // 移除连续重复项 auto removeIt = std::unique(sortedV.begin(), sortedV.end(), isDuplicate); sortedV.erase(removeIt, sortedV.end());
通用非连续去重方案(不依赖预排序)
如果你后续遇到完全没有预排序、重复项任意分布的场景,可以用带状态的谓词配合std::remove_if实现,通过集合记录已经出现过的键值,识别非连续重复项。注意该方案会占用额外内存存储已出现的键,适合数据量不大的场景:
#include <unordered_set> #include <string> std::unordered_set<std::string> existKeys; auto removeIt = std::remove_if(sortedV.begin(), sortedV.end(), [&existKeys](const Data& item) { // 组合唯一键:把POS和Record拼接作为去重依据,符合你的业务规则 std::string key = std::to_string(item.POS) + "_" + item.Record; if (existKeys.count(key)) { return true; // 键已存在,标记为待删除 } existKeys.insert(key); return false; // 键不存在,保留 }); sortedV.erase(removeIt, sortedV.end());
额外代码问题提示
你贴的示例代码存在几处容易引发崩溃的bug,建议一并修正:
- 用
malloc申请Data结构体内存没有初始化,直接拷贝字符串容易出现野值;C++中POD结构体建议直接声明栈变量使用,不需要手动malloc/free。 - 代码中混用了
d和sd两个未做关联的结构体指针,属于粘贴代码时的疏漏,运行时会触发内存访问错误。 - 文件打开失败后没有做返回处理,后续逻辑会继续操作无效的文件句柄。
内容的提问来源于stack exchange,提问作者Ankur Ghoshal
相关产品推荐
相关产品推荐

