在 IF 条件下进行多次检查

alternate to multiple checks in IF condition

本文关键字:检查 IF 条件下      更新时间:2023-10-16

有没有其他方法可以重写这段代码?

if(i == 0 || i == 4 || i == 6 || i == 8 || i == 9 || i == 19 || i == 198 || i == 41 )
{
     // do something
}

在 if 条件下忽略此多次检查的另一种方法是什么......我们是否有类似 IN 语句(SQL 查询)的内容C++?..提前谢谢..

通常情况下,编写一个新函数可以非常优雅:

template <typename Range, typename T>
bool contains(Range range, T element) {
    return std::find(std::begin(range), std::end(range), element) != std::end(range);
}
template <typename T>
bool contains(std::initializer_list<T> range, T element) {
    return contains<std::vector<int>>(range, element);
}

我选择了基于范围的方法,但您也可以提供采用开始/结束迭代器的重载。另外,请随意在实现中使用std::find以外的其他内容。

(我们真的必须超载std::initializer_list吗?似乎很奇怪,我们无法推断它。

现在我们可以写:

if (contains({1, 2, 3, 4, 5}, 3))

一个简单的开关盒是最易读的:

   switch (i) {
      case 0:
      case 4:
      case 6:
      case 8:
      case 9:
      case 19:
      case 198:
      case 41:
        // DO THINGS
        break;
      default:
        // OTHERS
    }

使用静态常量无序集合:

static const std::unordered_set<int> my = { 1 , 1 , 2 , 3 , 5 , 8 , 13 } ;
auto find = my.find( 8 ) ;
if( find != my.end() )
{
    cout << "found:" << *find << endl ;
}

搜索复杂度平均为 O(1)。

并且应该是线程安全的。

好吧,在 C 中(当然还有C++),您可以:

switch(i)
{
   case 0:
   case 4:
   case 6:
   case 8:
   case 9:
   case 19:
   case 198:
   case 41:  // do something
             break;
}

当然,编译器将生成与原始 if 几乎相同的代码,但也许这看起来更清晰?

编写这样的语句是一个错误

if(i = 0 || i = 4 || i = 6 || i = 8 || i = 9 || i = 19 || i = 198 || i = 41 )

您需要 == 运算符进行比较。现在,既然您正在比较一种类型的值与多种类型的值。使用开关语句是更好的解决方案。快乐编码

static const int options[] = {0, 4, 6, 8, 9, 19, 198, 41};
if (std::find(std::begin(options), std::end(options), i) != options.end()) {
    // do something
}

如评论中所述,只要您保持选项排序,就可以使用它

static const int options[] = {0, 4, 6, 8, 9, 19, 198, 41};
if (std::binary_search(std::begin(options), std::end(options), i)) {
    // do something
}

这应该更快。

对于小数组,我认为选择哪种变体并不重要。

将初始值设定项列表(或向量)与 std::any_of 一起使用:

static const auto accepted = { 0, 4, 6, 8, 9, 19, 198, 41 };
if( std::any_of(std::begin(accepted), std::end(accepted),
    [&i](int x) { return i == x; }) {
    // do something
}

(这是@JosephMansfield在评论中提出的)

编辑:这可以通过对整数值重新排序来优化,首先针对命中率最高的值进行优化。

您可以使用 STL MAP ...试试这个..

#include<cstdio>
#include<map>
using namespace std;
map<int,int>mp;
int main()
{
    int i;
    mp[0]=mp[4]=mp[6]=mp[8]=mp[9]=mp[19]=mp[198]=mp[41]=1;
    scanf("%d",&i);
    if(mp[i])
    {
        //do something
    }
    return 0;
}

使用像这样的简短固定列表,您可以查找一个整数n,以便所有元素在除以 n 时具有不同的余数。例如,n = 14在这里可以解决问题,因为余数mod 14是 0、4、6、8、9、5、2 和 13。所以你可以这样做:

static const int remainder_table[14] = {
    0, 0, 198, 0, 4, 19, 6, 0, 8, 9, 10, 0, 0, 41
} ;
if (remainder_table[i % 14] == i) {
    // do something
}

警告:这不一定比原始if语句更快!这取决于硬件划分的速度和编译器的优化能力。

如果你想将i与常量进行比较 - 这是在合规时已知的,你可以使用TMP。

namespace detail
{
    template <int ...Args>
    struct CompFunc;
    template <int num, int ...Args>
    struct CompFunc<num, Args...>
    {
        static constexpr bool f(int i)
        {
            return (i == num) || CompFunc<Args...>::f(i);
        }
    };
    template <>
    struct CompFunc<>
    {
        static constexpr bool f(int i)
        {
            return false;
        }
    };
}
template <int ...Args>
constexpr bool any_of_const(int i)
{
    return detail::CompFunc<Args...>::f(i);
}

if (any_of_const<0, 4, 6, 8, 9, 19, 198, 41>(i))
{
    ...
}

(现场示例)