C++ std::set使用自定义比较器时如何按类成员a查找元素
原代码sa.find(3)无匹配结果的原因
std::set::find的匹配逻辑是找到满足!comp(key, element) && !comp(element, key)的元素,也就是当前比较器定义下和key等价的元素。
你第一个版本的比较器中,传入int类型参数时,比较逻辑是把int值优先和Example的b成员比较,相等时再和a成员比较。你传入的key是3,相当于要找b==3 且 a==3的Example实例,但你插入的元素里b=3的两个实例a分别是5和4,没有符合等价条件的元素,自然返回end()。
你第二个版本的比较器把int值和a成员做比较,且排序主键就是a,所以传入3的时候就能匹配到a==3的元素,符合逻辑。
按(b降序,a降序)排序时,查找第一个a等于指定值的元素的实现方案
因为你当前set的排序规则是优先按b降序、再按a降序,a成员不是排序的第一维度,set本身的有序结构没有针对a做索引,所以无法直接用自带的find高效查找,有两种可选方案:
方案1:线性遍历查找
如果数据量不大,直接遍历整个set匹配第一个a等于目标值的元素即可:
// 查找第一个a等于target的元素 int target = 3; auto it = sa.end(); for (auto iter = sa.begin(); iter != sa.end(); ++iter) { if (iter->a == target) { it = iter; break; } } if (it != sa.end()) { cout << it->a << " " << it->b << endl; }
方案2:额外维护索引结构
如果数据量大、查找操作频繁,可以额外维护一个std::multimap或者std::unordered_multimap存储a值到set迭代器的映射,插入/删除元素时同步更新映射,查找时直接查映射即可获得O(logn)或者O(1)的查找效率。
方案3:修改查找的key构造逻辑(仅适用于按排序规则维度查找的场景)
如果你的需求实际是查找b等于指定值的元素,直接按照比较器的逻辑传入对应的key即可,比如你要找b=3的第一个元素,直接传3就会匹配到b=3、a最大的那个元素(也就是你示例里的(5,3))。
内容的提问来源于stack exchange,提问作者Imam Mohammad Bokhary
相关产品推荐
相关产品推荐

