使用Mask进行过滤
遇到一个需求,依据传进来的filter的结构体来进行过滤,返回过滤结果的vector大小。
typedef struct
{
int myMask;
int ...;
}ObjectFilter;
filter内含多个条件,其中除了常规需求filter,还有一个类似掩码的mask。mask的取值为0-15,即四位的二进制数(0000-1111),其中四位分别表示另一个enum属性的取值(可以多位为true),分别为1(0001)、2(0010)、4(0100)、8(1000)。上一层的应用传入0-15的mask值,后端根据此mask值,解析出来这enum属性的取值,再分别处理。
注意点:
① 常规需求放在前面,不符合规则的过滤掉。mask需求放在后面,根据传进来的mask(可转换为4位的二进制),判断该enum值的取值,四位都过滤完之后,再执行insert到set的操作。对于未传入mask的情况,则经过normal filter之后,直接push到vector即可。
② mask的处理,使用移位(对二进制除以2)和 对2取模(除以2取余数)完成。哪位为0,则进入哪位的if判断中,则进行对应处理,全0的则不会进入mask处理里面来。
③ 上一步中,对于一个mask,每一位为true的do something函数体里面,可能有pObjectVec的处理,但是对于四位来说,肉具体逻辑包含”某一位为1的时候就将该object放入vector”的逻辑的话,最后会导致有多个1的mask的结果里面有重复的object,所以在进入mask判断前后可以做一个set和vector的互相转换。vector转换为set,直接使用set的构造函数;set转换为vector,使用vector的assign方法。
int getObjectByFilter(const ObjectFilter& pConfig, vector<Object*> &pObjectVec)
{
for(auto lIter = mObjectMap.begin(); lIter != mObjectMap.end(); lIter++)
{
// check some normal thing
if (...)
{
continue;
}
// construct a set, make sure vector elements unique
std::set<MyObject*> lObjectSet(pObjectVec.begin(), pObjectVec.end());
// myMask = 13 : 1101
if (pConfig.myMask)
{
// 1101 --> true
if (pConfig.myMask % 2)
{
// do something
// eg. lObjectSet.insert(lIter->second);
}
//110 --> false
if ((pConfig.myMask>>1) % 2)
{
// do something
}
//11 --> true
if ((pConfig.myMask>>2) % 2)
{
// do something
}
//1 --> true
if ((pConfig.myMask>>3) % 2)
{
// do something
}
pObjectVec.assign(lObjectSet.begin(), lObjectSet.end );
}
else
{
pObjectVec.push_back(lIter->second);
}
}
return pObjectVec.size();
}
注:经老师提醒,可以使用按位与和按位或来实现以上需求:
int getObjectByFilter(const ObjectFilter& pConfig, vector<Object*> &pObjectVec)
{
for(auto lIter = mObjectMap.begin(); lIter != mObjectMap.end(); lIter++)
{
// check some normal thing
if (...)
{
continue;
}
if (pConfig.mUserRoleMask && pConfig.mUserId)
{
// 后部分是0001 | 0010
if (pConfig.myMask & ((uint32)enum_type_A | (uint32)enum_type_B))
{
if (...)
{
// do something
// eg. pObjectVec.push_back(lIter->second);
continue;
}
}
...
}
else
{
pObjectVec.push_back(lIter->second);
}
}
return pObjectVec.size();
}