C++ 如果条件允许,可替代多次检入

C++ 如果条件允许,可替代多次检入,c++,if-statement,C++,If Statement,是否有其他方法重新编写此代码 if(i == 0 || i == 4 || i == 6 || i == 8 || i == 9 || i == 19 || i == 198 || i == 41 ) { // do something } 在if条件下,忽略此多个检查的另一种方法是什么。。。我们有什么类似于C++中的StastsSQL查询吗?提前谢谢 static const int options[] = {0, 4, 6, 8, 9, 19, 198, 41}; if (std

是否有其他方法重新编写此代码

if(i == 0 || i == 4 || i == 6 || i == 8 || i == 9 || i == 19 || i == 198 || i == 41 )
{
     // do something
}
在if条件下,忽略此多个检查的另一种方法是什么。。。我们有什么类似于C++中的StastsSQL查询吗?提前谢谢

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
}
这应该更快

对于小型阵列,我认为选择哪种变体并不重要

正如在评论中提到的,只要对选项进行排序,就可以使用此选项

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
}
这应该更快


对于小型阵列,我认为选择哪种变体并不重要。

您可以使用STL映射。。。试试这个

#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;
}

您可以使用STL映射。。。试试这个

#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;
}

使用静态常量无序集:

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 ;
}
搜索复杂度平均为O1


并且应该是线程安全的。

使用静态常量无序集:

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 ;
}
搜索复杂度平均为O1


应该是线程安全的。

嗯,在C中,当然,C++,你可以:

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

当然,编译器会产生与你原来的IFS代码差不多的代码,但是这个看起来更清晰了?

< P>,在C中,当然,C++,你可以:

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

当然,编译器生成的代码与您原来的一组ifs几乎相同,但这看起来可能更清晰?

一个简单的开关案例是最容易阅读的:

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

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

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

写这样的陈述是错误的

if(i = 0 || i = 4 || i = 6 || i = 8 || i = 9 || i = 19 || i = 198 || i = 41 )
您需要==运算符进行比较。
现在,因为您正在比较一种类型的值和多种类型的值。使用switch语句是更好的解决方案。快乐编码

写这样的语句是错误的

if(i = 0 || i = 4 || i = 6 || i = 8 || i = 9 || i = 19 || i = 198 || i = 41 )
您需要==运算符进行比较。
现在,因为您正在比较一种类型的值和多种类型的值。使用switch语句是更好的解决方案。快乐编码

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

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);
}

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

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::any_一起使用:

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在评论中提出的


编辑:可以通过对整数值重新排序进行优化,首先优化最大命中值。

使用初始值设定项列表或带有std::任意值的向量:

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在评论中提出的


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

对于这样一个简短的固定列表,您可以查找整数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语句快!这取决于硬件除法的速度和编译器的优化功能。

对于这样一个简短的固定列表,您可以查找整数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);
}

如果你想把i和常数进行比较——这在complie时间是已知的,你可以使用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);
}



可能是,将它们放入数组并使用std::find?将数字按排序顺序排列,然后使用std::binary_search?或std::any_of与绑定的std::equal或lambda。值得指出的是,您的=s应该是==s。@KerrekSB对于这几个,可能不值得费心。可能是,将它们放在一个数组中,然后使用std::find?将数字按顺序排序,然后使用std::binary_search?或std::any_of,并使用绑定std::equal或lambda。值得指出的是,你的=s应该是==s。@KerrekSB对于这几个,可能不值得费心。我想,通过更数据驱动,它肯定会有所改进。但是IMHO ifs可能会更快,而选项的数量却很少。如果您确保选项被排序,那么您可以使用std::binary_搜索而不是std::findIt。我想,通过更加数据驱动,它肯定会有所改进。但是IMHO ifs可能会更快,而选项数量较少如果您确保选项已排序,您可以使用std::binary_搜索而不是std::findOf当然,编译器…:不一定是真的!例如,编译器可以优化这样的switch语句以执行二进制搜索。或者构建一个跳转表,但不是在这种情况下。switch语句应该至少和if语句一样快。我喜欢这样。几乎和直觉一样。我真的不喜欢这种方法。如果我看到一个开关,我预计会有多个不同的情况。我会很快弄明白的,但还是有点不协调。@TonyK:编译器可以

对if语句应用相同的优化。@JosephMansfield:这就是为什么使用default:break;//当然,编译器……不一定是真的!例如,编译器可以优化这样的switch语句以执行二进制搜索。或者构建一个跳转表,但不是在这种情况下。switch语句应该至少和if语句一样快。我喜欢这样。几乎和直觉一样。我真的不喜欢这种方法。如果我看到一个开关,我预计会有多个不同的情况。我会很快找到答案,但还是有点不协调。@TonyK:编译器可以对if语句应用相同的优化。@JosephMansfield:这就是为什么使用default:break;//不要做灾难性的事!如果条目不存在,mp[i]将创建该条目。如果议员findi!=mp.end.mp[i]实际上可以工作,因为我认为整数的默认值是0。。。但无论如何,这不是正确的方式。。太慢了。plus被分配到堆中,用于从某人处偷窃或抢劫。特别是jewerly和其他贵重物品:你想说的是,是的。。。抱歉成为语法纳粹,但这太有趣了!如果条目不存在,mp[i]将创建该条目。如果议员findi!=mp.end.mp[i]实际上可以工作,因为我认为整数的默认值是0。。。但无论如何,这不是正确的方式。。太慢了。plus被分配到堆中,用于从某人处偷窃或抢劫。特别是jewerly和其他贵重物品:你想说的是,是的。。。很抱歉成为语法纳粹,但这太有趣了这可能是答案的美丽之处,非常可读。。但这和其他的相比有多快呢?或者更确切地说,它的速度有多慢?@paldin它的速度必须和它的实现速度一样快。如果std::find不够好,请更改它!:DIt最好使用container::find,因为它们专门用于容器的实现。。但这和其他的相比有多快呢?或者更确切地说,它的速度有多慢?@paldin它的速度必须和它的实现速度一样快。如果std::find不够好,请更改它!:DIt最好使用container::find,因为它们专门用于容器的实现。我发现,特别是对于较小的集合,std::set往往比std::unordered_set更快。虽然std::unordered_set::find的时间复杂度更好,但常量成本似乎大于std::set::find中二进制搜索的成本。@BartvanNierop,因为此容器只构造了一次,更低的查找成本更为重要。@2015我的意思是,std::unordered_set::find的一次查找成本比std::set::find的几次查找成本更高。见和。时间复杂性并不是一切,还必须考虑到每个单独操作的成本。@BartvanNierop是的,对于较小的值,set更快,但在某些时候>~250个元素,如果按排序顺序插入,无序会更快。测量用例是最好的选择。我发现,特别是对于较小的集合,std::set往往比std::unordered_set更快。虽然std::unordered_set::find的时间复杂度更好,但常量成本似乎大于std::set::find中二进制搜索的成本。@BartvanNierop,因为此容器只构造了一次,更低的查找成本更为重要。@2015我的意思是,std::unordered_set::find的一次查找成本比std::set::find的几次查找成本更高。见和。时间复杂性并不是一切,还必须考虑到每个单独操作的成本。@BartvanNierop是的,对于较小的值,set更快,但在某些时候>~250个元素,如果按排序顺序插入,无序会更快。测量用例是最好的选择。是的。的任何_在语义上等同于调用std::find_if并将结果与序列结尾进行比较,以便对第一个匹配项执行线性搜索。Yes。的任何_在语义上等同于调用std::find_if并将结果与序列结尾进行比较,以便对第一个匹配执行线性搜索。