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

如何在单个std::set中比较结构体的两个属性?

解决std::set中基于结构体双属性(id数组)的查找问题

首先先提一下代码里的小笔误:你定义的比较器类是ComparePager,但std::set的模板参数写的是CompareABC,得把类名统一成CompareABC才能正常编译,我先修正这个问题再讲查找方案。

方案一:利用std::set的有序性快速查找(O(log n)效率)

因为你的std::set已经用CompareABC按照id数组排序了,所以可以直接构造一个包含目标id的临时ABC_PTR,然后调用set::find方法。这个方法利用了set的红黑树结构,查找效率很高。

修正后的完整代码示例:

#include <set>
#include <memory>
#include <cstring>
#include <afxstr.h> // 针对CString的头文件

struct ABC { 
    CString name; 
    byte id[2]; 
}; 
typedef std::shared_ptr<ABC> ABC_PTR; 

// 统一比较器类名,和set的模板参数匹配
class CompareABC { 
public: 
    bool operator()(const ABC_PTR& m1, const ABC_PTR& m2) const { 
        if (m1->id[0] == m2->id[0]){ 
            return m1->id[1] < m2->id[1]; 
        } 
        return m1->id[0] < m2->id[0]; 
    } 
}; 

std::set<ABC_PTR, CompareABC> g_ABCSet; 

// 查找函数示例
void findABCById(const byte targetId[2]) {
    // 构造临时ABC对象,只需要设置目标id,name不影响查找(因为比较器只看id)
    auto tempABC = std::make_shared<ABC>();
    memcpy(tempABC->id, targetId, sizeof(tempABC->id));

    auto it = g_ABCSet.find(tempABC);
    if (it != g_ABCSet.end()) {
        // 找到匹配元素
        wprintf(L"Found element: name = %s, id = 0x%02X%02X\n", 
            (*it)->name.GetString(), (*it)->id[0], (*it)->id[1]);
    } else {
        wprintf(L"Element with id 0x%02X%02X not found\n", targetId[0], targetId[1]);
    }
}

调用的时候只需要传入目标id数组即可,比如:

byte target[2] = {0x01, 0x02};
findABCById(target);

方案二:用std::find_if线性遍历查找(更灵活)

如果你不想构造临时对象,或者需要更复杂的匹配逻辑,可以用std::find_if结合lambda表达式遍历整个set。这种方法是线性时间复杂度O(n),适合元素数量不多的场景。

代码示例:

#include <algorithm> // 用于std::find_if

void findABCByIdLinear(const byte targetId[2]) {
    auto it = std::find_if(g_ABCSet.begin(), g_ABCSet.end(), 
        [&targetId](const ABC_PTR& ptr) {
            // 直接比较两个id字节是否完全匹配
            return ptr->id[0] == targetId[0] && ptr->id[1] == targetId[1];
        });

    if (it != g_ABCSet.end()) {
        wprintf(L"Found element: name = %s, id = 0x%02X%02X\n", 
            (*it)->name.GetString(), (*it)->id[0], (*it)->id[1]);
    } else {
        wprintf(L"Element with id 0x%02X%02X not found\n", targetId[0], targetId[1]);
    }
}

关键注意事项

  • 确保比较器的排序逻辑和查找时的匹配逻辑一致:你的比较器是按id[0]优先、id[1]次之的顺序排序,查找时必须保证两个字节都相等才视为匹配,这样才不会出现逻辑错误。
  • 构造临时对象时,不需要初始化name成员,因为CompareABC只比较id,set的find方法只会根据比较器的规则来判断是否匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:35:23