CuriousToLearn
CuriousToLearn

Reputation: 153

alternate to multiple checks in IF condition

is there some other way to re-write this code?

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

what is the other way to ignore this multiple checks in the if condition... do we have anything like IN statements(SQL queries) in C++?.. Thanks in advance..

Upvotes: 1

Views: 513

Answers (10)

ikh
ikh

Reputation: 10427

If you want to compare i with constant - which is known at complie time, you can use 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);
}

and

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

(live example)

Upvotes: 0

TonyK
TonyK

Reputation: 17124

With a short, fixed list like this, you can look for an integer n such that all the elements have a different remainder when divided by n. For instance, n = 14 does the trick here, because the remainders mod 14 are 0, 4, 6, 8, 9, 5, 2, and 13. So you can do this:

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
}

Warning: This is not necessarily faster that the original if-statement! That depends on the speed of hardware division, and the compiler's optimising capabilities.

Upvotes: 0

utnapistim
utnapistim

Reputation: 27385

Use an initializer list (or vector) with 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
}

(this was proposed by @JosephMansfield in a comment)

Edit: This can be optimized by reordering the integer values, optimizing for the most hit value first.

Upvotes: 1

graywolf
graywolf

Reputation: 7520

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
}

As mentioned in the comments, as long as you keep options sorted, you can use this

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
}

which should be faster.

For small array I think it doesn't really matter which variant you pick.

Upvotes: 1

Joseph Mansfield
Joseph Mansfield

Reputation: 110768

As is often the case, writing a new function can be very elegant:

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

I went for the range-based approach, but you could provide overloads that take begin/end iterators too. Also, feel free to use something other than std::find in the implementation.

(Do we really have to overload for std::initializer_list? Seems strange that we can't deduce it.)

Now we can write:

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

Upvotes: 4

Ali Kazmi
Ali Kazmi

Reputation: 1458

Writing such statement is an error

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

You require == operator for comparison. Now since you are comparing one type of value against multiple. using switch statement is better solution. Happy Coding

Upvotes: 1

2501
2501

Reputation: 25753

Use a static const unordered set:

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

The search complexity is on average O(1).

And should be thread safe.

Upvotes: 2

Thomas8
Thomas8

Reputation: 1149

A simple switch-case is the most readible:

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

Upvotes: 2

Mawg
Mawg

Reputation: 40205

Well, in C (and also, of course, C++), you could:

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

Of course, the compiler will generate pretty much the same code as your original bunch of ifs, but maybe this looks clearer?

Upvotes: 1

Mukit09
Mukit09

Reputation: 3409

You can use STL MAP ... Try this..

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

Upvotes: 0

Related Questions