在C ++中有效地比较int与给定int的列表

时间:2017-06-13 06:53:13

标签: c++

是否有一种有效/优雅的方法来比较int中的int与C ++中的给定int。假设我有四个数字:P,Q,R,S和我需要将它们与给定的int T进行比较以得到不同的情况。

if (P == T && Q != T && R != T && S != T) case('P'); else if (P != T && Q == T && R != T && S != T) case('Q'); else if (P != T && Q != T && R == T && S != T) case('R'); else if (P != T && Q != T && R != T && S == T) case('S');

同样地,我将有6个配对案例:PQ,QR,PR ......,4个三联案件和1个四重案件。正如你所看到的,很多明确的比较!有没有一种优雅的方法来使用STL容器?

我需要其中一个案例作为我的输出:'P','Q',..,'PQ','RS',..'PQR','PQS'......'PQRS'。我打算做一个switch-case,因为所有这些组合都会调用不同的代码。

3 个答案:

答案 0 :(得分:5)

使用带有布尔元组的查找映射作为键:

std::map<std::tuple<bool,bool,bool,bool>,value> map;

查找价值就是这样:

map.find({T==P,T==Q,T==R,T==S});

(将它包装在查找函数中以使其更容易)。

地图的价值将决定您实际需要的是什么。如果找到密钥,它可以是字符串,数值,甚至是std :: function(lambda)。

或者你也可以使用unordered_map,但是你需要自己提供一个哈希函数,因为STL没有元组的默认哈希函数。

答案 1 :(得分:3)

您可以使用按位运算将四个测试的结果合并为一个0..15整数值。请注意,每次比较只执行一次。

获得结果值后,它可以用作数组或std::vector的索引或关联容器中的键查找。我在这个简单的例子中使用了switch和结果。

int mask = (P == T) << 3 | (Q == T) << 2 | (R == T) << 1 | (S == T);

switch (mask) // 0..15
{
    case 15: // PQRS
        break;
    case 14: // PQR
        break;
    case 13: // PQS
        break;
    case 12: // PQ
        break;
    case 11: // PRS
        break;
    case 10: // PR
        break;
    case 9: // PS
        break;
    case 8: // P
        break;
    case 7: // QRS
        break;
    case 6: // QR
        break;
    case 5: // QS
        break;
    case 4: // Q
        break;
    case 3: // RS
        break;
    case 2: // R
        break;
    case 1: // S
        break;
    case 0: // none
        break;
}       

答案 2 :(得分:2)

尝试匹配位字段。

如果我们考虑一个4位字段0000,我们可以设置第一位,如果T==P第二位T==Q,依此类推:

unsigned index{(P==T?1U:0U)|(Q==T?2U:0U)|(R==T?4U:0U)|(S==T?8U:0U)};

然后只需索引到一个数组。

注意1:我注意到使用switch相同技巧的另一个答案也可以。

注意2:您可以将此实现视为使用“完美哈希”的哈希表。

#include <iostream>
#include <string>

//Actual Solution Starts Here.

const std::string match_data[] {
 "",//0000
 "P",//0001
 "Q",//0010
 "PQ",//0011
 "R",//0100
 "PR",//0101
 "PQ",//0101
 "PQR",//0111
 "S",//1000
 "PS",//1001
 "QS",//1010
 "PQS",//1011
 "RS",//1100
 "PRS",//1101
 "PQS",//1101
 "PQRS"//1111
};


std::string match(int T, int P, int Q, int R, int S){
    unsigned index{(P==T?1U:0U)|(Q==T?2U:0U)|(R==T?4U:0U)|(S==T?8U:0U)};
    return match_data[index];
}

//Actual Solution Ends Here.

//The rest is a trivial test harness...

bool error{false};

int check(int T, int P, int Q, int R, int S, const std::string& expect){
    const auto result{match(T,P,Q,R,S)};
    if(result!=expect){
        std::cout<<"Error ("<<T<<','<<P<<','<<Q<<','<<R<<','<<S<<")=="<<result<<"!="<<expect<<std::endl;
        error=true;
        return 1;
    }
    return 0;
}


int main() {
    int errors{0};

    errors+=check(7,1,2,3,4,"");
    errors+=check(7,7,2,3,4,"P");
    errors+=check(9,1,9,3,4,"Q");
    errors+=check(117,1,6,117,4,"R");
    errors+=check(13,1,7,3,13,"S");
    errors+=check(132,132,132,132,132,"PQRS");
    errors+=check(98,98,98,3,4,"PQ");
    errors+=check(9876,56,87,9876,4,"R");
    errors+=check(1,1,0,1,0,"PR");
    errors+=check(78,78,78,78,0,"PQR");

    if(errors==0&&!error){
        std::cout<<"Success"<<std::endl;
    }else{
        std::cout<<"ERRORS: "<<errors<<std::endl;
    }
    return 0;
}