簡體   English   中英

將變量與多個值進行比較的最有效方法?

[英]Most efficient way to compare a variable to multiple values?

在我的程序中有幾次,我不得不檢查一個變量是否是許多選項之一。 例如

if (num = (<1 or 2 or 3>)) { DO STUFF }

我已經搞砸了“或”,但似乎沒有什么是正確的。 我試過了

if (num == (1 || 2 || 3))

但它什么也沒做。

我想方便地區分幾個組。 例如

if (num = (1,2,3))

else if (num = (4,5,6))

else if (num = (7,8,9))

這是 C++11 中的一種方法,使用std::initializer_list

#include <algorithm>
#include <initializer_list>

template <typename T>
bool is_in(const T& v, std::initializer_list<T> lst)
{
    return std::find(std::begin(lst), std::end(lst), v) != std::end(lst);
}

有了它,你可以這樣做:

if (is_in(num, {1, 2, 3})) { DO STUFF }

盡管不與內置類型一起使用時,它不是很有效。 int可以正常工作,但是如果您比較std::string變量,例如,生成的代碼就很糟糕。

但是,在 C++17 中,您可以改用更有效的解決方案,該解決方案適用於任何類型:

template<typename First, typename ... T>
bool is_in(First &&first, T && ... t)
{
    return ((first == t) || ...);
}

// ...

// s1, s2, s3, s4 are strings.
if (is_in(s1, s2, s3, s4)) // ...

C++11 版本在這里效率非常低,而這個版本應該產生與手寫比較相同的代碼。

如果您要檢查的值足夠小,您可以為您尋找的值創建一個位掩碼,然后檢查該位是否被設置。

假設,您關心幾個組。

static const unsigned values_group_1 = (1 << 1) | (1 << 2) | (1 << 3);
static const unsigned values_group_2 = (1 << 4) | (1 << 5) | (1 << 6);
static const unsigned values_group_3 = (1 << 7) | (1 << 8) | (1 << 9);    
if ((1 << value_to_check) & values_group_1) {
  // You found a match for group 1
}
if ((1 << value_to_check) & values_group_2) {
  // You found a match for group 2
}
if ((1 << value_to_check) & values_group_3) {
  // You found a match for group 3
}

您必須與每個值進行比較。 例如

if (num == 1 || num == 2 || num == 3) { stuff }

我剛剛遇到了類似的問題,我來到了這些 C++11 解決方案:

template <class T> 
struct Is 
{ 
  T d_; 
  bool in(T a) { 
    return a == d_; 
  } 
  template <class Arg, class... Args> 
  bool in(Arg a, Args... args) { 
    return in(a) || in(args...); 
  } 
}; 

template <class T> 
Is<T> is(T d) { 
  return Is<T>{d}; 
}

或者作為沒有遞歸終止方法的替代方案。 請注意,這里的比較順序是未定義的,並且如果找到第一個匹配項,則不會提前終止。 但是代碼更緊湊。

template <class T>
struct Is {
  const T d_;
  template <class... Args>
  bool in(Args... args) {
    bool r{ false }; 
    [&r](...){}(( (r = r || d_ == args), 1)...);
    return r;
  }
};

template <class T>
Is<T> is(T d) { 
  return Is<T>{d}; 
}

因此,對於這兩種解決方案,代碼如下所示:

if (is(num).in(1,2,3)) {
  // do whatever needs to be done
}

您可以定義一組整數,將所需的值添加到其中,然后使用 find 方法查看有問題的值是否在集合中

std::set<int> values;
// add the desired values to your set...
if (values.find(target) != values.end())
    ...

我需要為枚舉做類似的事情。 我有一個變量,並希望根據一系列值對其進行測試。

在這里,我使用了可變參數模板函數。 請注意const char*類型的特化,因此is_in( my_str, "a", "b", "c")具有my_str存儲"a"時的預期結果。

#include <cstring> 

template<typename T>
constexpr  bool is_in(T t, T v) {
  return t == v;
}

template<>
constexpr  bool is_in(const char* t, const char* v) {
  return std::strcmp(t,v);
}

template<typename T, typename... Args>
constexpr bool is_in(T t, T v, Args... args) {
  return  t==v || is_in(t,args...);
}

示例用法:

enum class day
{
  mon, tues, wed, thur, fri, sat, sun
};

bool is_weekend(day d)
{
  return is_in(d, day::sat, day::sun);
}
float n;
if (n<1) exit(0);  
if (n / 3 <= 1)  
   // within 1, 2, 3
else if (n / 3 <= 2)  
   // within 4, 5, 6  
else if (n / 3 <= 3)  
   // within 7, 8, 9

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM