代码之家  ›  专栏  ›  技术社区  ›  Mykola Golubyev

C++将一堆值与给定值进行比较

c++
  •  3
  • Mykola Golubyev  · 技术社区  · 17 年前

    我需要将一个给定值与检索到的值进行比较。我在代码中多次这样做。我对它的外观不满意,我正在寻找某种util函数。有人写过吗?

    我正在比较的值的数量在编译时是已知的。


    如果

    #include <algorithm>
    #include <string>
    #include <vector>
    
    std::string getValue1()
    {
        return "test";
    }
    
    std::string getValue2()
    {
        return "the";
    }
    
    std::string getValue3()
    {
        return "world";
    }
    
    int main()
    {
        const std::string value = "the";
    
        // simple if
        if ( value == getValue1() ||
             value == getValue2() ||
             value == getValue3() )
            return 1;
    
        // using collections like vector, set
        std::vector<std::string> values;
        values.push_back( getValue1() );
        values.push_back( getValue2() );
        values.push_back( getValue3() );
        if ( values.end() != std::find( values.begin(), values.end(), value ) )
            return 1;
    
        // third option I'd use instead
        //
    
        return 0;
    }
    
    10 回复  |  直到 17 年前
        1
  •  7
  •   Joao da Silva    17 年前

    如果您要查找的值与运算符可比<(如int、float和std::string),那么使用std::set将值放在那里,然后检查set.find(value)==set.end()会更快。这是因为该集合将以一定的顺序存储值,从而允许更快的查找。使用哈希表会更快。然而,对于少于50个左右的值,你可能不会注意到任何差异:)所以我的经验法则是:

    • 5个或更多:放入集合或哈希表中

        2
  •  3
  •   Antti Huima    17 年前

    template <typename T>
    bool InSet(const T & item, const T & i1, const T & i2) {
      return item==i1 || item==i2;
    }
    
    template <typename T>
    bool InSet(const T & item, const T & i1, const T & i2, const T & i3) {
      return item==i1 || item==i2 || item==i3;
    }
    

    请注意,您可以通过创建具有不同数量参数的多个模板,使InSet像使用可变数量的参数一样工作。

    然后:

    int i;
    if (InSet(i, 3, 4, 5)) { ... }
    string s;
    if (InSet(s, "foobar", "zap", "garblex")) { ... }
    

    等等

        3
  •  1
  •   Salman A    17 年前

    根据您的要求

    if (InSet(value)(GetValue1(), GetValue2(), GetValue3()))
    {
       // Do something here...
    }
    

    template <typename T>
    class InSetHelper
    {
         const T &Value;
         void operator=(const InSetHelper &);
    public:
         InSetHelper(const T &value) : Value(value) {}
    
         template<class Other, class Another>
         bool operator()(const Other &value1, const Another &value2) const
         {
             return Value == value1 || Value == value2;
         }
         template<class Other, class Another, class AThird>
         bool operator()(const Other &value1, const Another &value2, const AThird &value3) const
         {
             return Value == value1 || Value == value2 || Value == value3;
         }
    };
    
    template <typename T> 
    InSetHelper<T> InSet(const T &value) { return InSetHelper<T>(value); }
    

    不过,这种语法可能更清楚:

    if (MakeSet(GetValue1(), GetValue2(), GetValue3()).Contains(value))
    {
       // Do something here...
    }
    
    template <typename T, typename U, typename V>
    class Set3
    {
        const T& V1;
        const U& V2;
        const V& V3;
        void operator=(const Set3 &);
    public:
        Set3(const T &v1, const U &v2, const V &v3) : V1(v1), V2(v2), V3(v3) {}
    
        template <typename W>
        bool Contains(const W &v) const
        {
            return V1 == v || V2 == v || V3 == v;
        }
    };
    
    template <typename T, typename U>
    class Set2 
    { 
         // as above 
    };
    
    template <typename T, typename U, typename V>
    Set3<T, U, V> MakeSet(const T &v1, const U &v2, const V &v3)
    {
        return Set3<T, U, V>(v1, v2, v3);
    }
    
    template <typename T, typename U>
    Set3<T, U> MakeSet(const T &v1, const U &v23)
    {
        return Set3<T, U, V>(v1, v2);
    }
    

    如果这些值真的是树或链表的一部分,那么你已经有了你的集合/容器,最好的办法就是使用一些递归:

    parent.ThisOrDescendantHasValue(value);
    

    您只需将此添加到父级和子级所属的任何类中:

    class Node
    {
    public: 
        Value GetValue();
        Node *GetChild();
        bool ThisOrDescendantHasValue(const Value &value)
        {
            return GetValue() == value
               || (GetChild() && GetChild->ThisOrDescendantHasValue(value));
        }
    };
    
        4
  •  1
  •   Mr.Ree    17 年前

    std::set 或a std::矢量 std::set_intersection()

    #include <set>
    #include <iostream>
    #include <iterator>
    using namespace std;
    
    #define COUNT(TYPE,ARRAY)  ( sizeof(ARRAY) / sizeof(TYPE) )
    
    inline bool CaseInsensitiveCompare (const char * a, const char * b)
      {  return strcasecmp( a, b ) < 0;  }
    
    int  main()
    {
      const char * setA[] = { "the", "world", "is", "flat" };
      const char * setB[] = { "the", "empty", "set", "is", "boring" };
    
      stable_sort( setA,  setA + COUNT( const char *, setA ),
                   CaseInsensitiveCompare );
    
      stable_sort( setB,  setB + COUNT( const char *, setB ),
                   CaseInsensitiveCompare );
    
      cout << "Intersection of sets:  ";
      set_intersection( setA, setA + COUNT( const char *, setA ),
                        setB, setB + COUNT( const char *, setB ),
                        ostream_iterator<const char *>(cout, " "),
                        CaseInsensitiveCompare );
      cout << endl << endl;
    }
    

    或者,考虑到你的1-N查找问题:
    排序!)

    if ( binary_search( setA, setA + COUNT( const char *, setA ),
                "is", CaseInsensitiveCompare ) )
      ...
    
    if ( binary_search( setA, setA + COUNT( const char *, setA ),
                "set", CaseInsensitiveCompare ) )
      ...
    
        5
  •  1
  •   wchung    17 年前

        6
  •  0
  •   MSN    17 年前

    std::find_first_of .

    当然,如果你只关心找到一个值,你可以创建自己的包装器 std::find .

        7
  •  0
  •   JSBÕ±Õ¸Õ£Õ¹    17 年前

        8
  •  0
  •   John Ellinwood    17 年前

    我喜欢集合方法,也许使用hash_set而不是vector。将值存储在属性文件中,并有一个方法从文件中填充hash_set,如果值在hash_set中,则有另一个方法返回布尔值。然后,您可以在主代码中找到一行2行。

        9
  •  0
  •   Patrick    17 年前

    这取决于检索值的来源,如果你从文件或流中读取,那么你会做一些不同的事情,但如果你的来源是一系列函数,那么以下是一种不同的方法,虽然不完美,但可能适合你的需求:

    const int count = 3;
    std::string value = "world";
    boost::function<std::string(void)> funcArray[count];
    funcArray[0] = &getValue1;
    funcArray[1] = &getValue2;
    funcArray[2] = &getValue3;
    
    for( int i = 0; i < count; ++i )
    {
        if( funcArray[i]() == value )
            return 1;
    }
    

    如果你知道哪些函数是源(以及对象的数量),我希望你可以使用预处理器组装函数指针数组。

        10
  •  0
  •   zdan    17 年前

    使用boost::array(或std::tr1::array)并创建这样一个简单的函数怎么样:

    template <typename ValueType, size_t arraySize>
    bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
    {
        return std::find(arr.begin(), arr.end(), val)!=arr.end();
    }
    

    然后,您可以很容易地重用它:

    #include <string>
    #include <iostream>
    
    #include <boost\array.hpp>
    
    template <typename ValueType, size_t arraySize>
    bool contains(const boost::array<ValueType, arraySize>& arr, const ValueType& val)
    {
        return std::find(arr.begin(), arr.end(), val)!=arr.end();
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        boost::array<std::string, 3> arr = {"HI", "there", "world"};
    
        std::cout << std::boolalpha 
            << "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
            << "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
            << "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
    
        return 0;
    }
    

    编辑: 因此,提振已经结束。将其调整为常规数组非常容易:

    template <typename ValueType, size_t arraySize>
    bool contains(ValueType (&arr)[arraySize], const ValueType& val)
    {
        return std::find(&arr[0], &arr[arraySize], val)!=&arr[arraySize];
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        std::string arr[3] = {"HI", "there", "world"};
    
        std::cout << std::boolalpha << "arr contains HI: " << contains(arr, std::string("HI")) << std::endl
            << "arr contains blag: " << contains(arr, std::string("blag") ) << std::endl
            << "arr contains there: " << contains(arr, std::string("there") ) << std::endl;
    
        return 0;
    }