我需要将一个给定值与检索到的值进行比较。我在代码中多次这样做。我不满意它的外观,我正在寻找某种类型的util函数。有谁写过一个?
我在比较的值的数量在编译时是已知的。
更新:我想摆脱容器,因为我知道确切的数值(通常不超过3)我想与之比较。每次将物品放入容器都不太方便 我不喜欢 if ,因为它并不像“查找”那样明显。
#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;
}
答案 0 :(得分:7)
如果您要查找的值与运营商的比较&lt; (比如int,float和std :: strings),那么使用std :: set将值放在那里然后检查set.find(value)== set.end()会更快。这是因为该集合将以特定顺序存储值,以便更快地进行查找。使用哈希表会更快。但是,对于少于50个值或者你可能没有注意到任何差异:)所以我的经验法则是:
少于5项:如果有多个||
5个或更多:放入集合或哈希表
答案 1 :(得分:3)
您可以编写一组模板函数来帮助您完成此操作,例如:
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")) { ... }
等
答案 2 :(得分:1)
std :: set 或 std :: vector 。只需使用 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查找问题:
(注意:使用 binary_search() AFTER 排序!)
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"is", CaseInsensitiveCompare ) )
...
if ( binary_search( setA, setA + COUNT( const char *, setA ),
"set", CaseInsensitiveCompare ) )
...
答案 3 :(得分:1)
根据您的要求
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)
哪个更改,'value'或'getValueX()'返回的值?您可以将所有内容插入到hash_map / map中,然后按照您对容器的建议进行搜索。
答案 5 :(得分:0)
std::find_first_of
。
当然,如果您只关心查找单个值,则可以围绕std::find
创建自己的包装器。
答案 6 :(得分:0)
我会推荐你的方法2,使用std :: vector或其他容器并寻找成员资格。由于您要检查的元素的顺序可能不相关,因此您可能希望使用std :: set或std :: map。如果你的值集合中有很多项目,那么使用集合或地图会更快,而如果只有少数,则矢量可能会更快。
这些方法中的任何一个的优点是,您可以将集合/映射存储在常见的位置,并避免每次都必须构建匹配响应集。
答案 7 :(得分:0)
我喜欢收藏方法,也许使用hash_set而不是vector。将值存储在属性文件中,并具有从文件中填充hash_set的方法,如果值在hash_set中,则返回另一个boolean值。然后你可以在主代码中找到一两行。
答案 8 :(得分:0)
这取决于检索到的值的来源,如果您从文件或流中读入,那么您将执行不同的操作,但如果您的源是一系列函数,那么以下是另一种方法,不完美但可能适合您的需求:
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;
}
如果您知道哪些函数是源(以及对象的数量),我希望您可以使用预处理器组装函数指针数组。
答案 9 :(得分:0)
如何使用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;
}