![](/img/trans.png)
[英]Why does case insensitive work with std::hash function for std::unordered_set?
[英]Case-Insensitive STL Containers (e.g. std::unordered_set)
制作std :: unordered_set CASE-INSENSITIVE容器的最短, 最跨平台的方法是什么?
my_set.insert("Apples");
my_set.insert("apples"); //Insert doesn't occur because of duplicate item
我知道STL提供Hash和Pred 。 哈什應該怎么做? Pred應該是什么? 如果它們不是內置的,那么請提供它們的代碼以及它們的使用示例(即如何聲明std::unordered_set
?)。
由於批評,我將詳細說明我要做的事情。 我需要一個高性能的透明HTTP代理服務器,它所做的一件事就是快速查找HTTP頭字段。 HTTP頭字段被定義為不區分大小寫,因此我需要一個不區分大小寫的容器。
unordered_set
的定義是
template <class Value,
class Hash = hash<Value>,
class Pred = std::equal_to<Value>,
class Alloc = std::allocator<Value> >
class unordered_set;
如果你提供不區分大小寫的Hash和Pred仿函數,那么集合也會變得如此。
這是一個簡單的例子,字符串哈希函數是簡單的,但您可以根據需要進行更改
struct MyHash
{
size_t operator()(const std::string& Keyval) const
{
//You might need a better hash function than this
size_t h = 0;
std::for_each( Keyval.begin() , Keyval.end() , [&](char c )
{
h += tolower(c);
});
return h;
}
};
struct MyEqual
{
bool operator()(const std::string& Left, const std::string& Right) const
{
return Left.size() == Right.size()
&& std::equal ( Left.begin() , Left.end() , Right.begin() ,
[]( char a , char b )
{
return tolower(a) == tolower(b);
}
);
}
};
int main()
{
std::unordered_set< std::string , MyHash , MyEqual > m;
m.insert( "Apple" );
m.insert( "apple" );
return 0;
}
我個人會定義一個不區分大小寫的值類型,並在最小的提示下轉換為字符串。 因此允許我使用標准的哈希和謂詞模型。
#include <string>
#include <unordered_set>
#include <iostream>
#include <algorithm>
#include <iterator>
class LCString
{
std::string data;
public:
operator std::string&() {return data;}
operator std::string const&() const {return data;}
LCString(char const* init)
{
std::transform(init, init + strlen(init),
std::back_inserter(data), &::tolower);
}
};
int main()
{
typedef std::unordered_set<LCString,
std::hash<std::string>,
std::equal_to<std::string> > MySet;
MySet data;
data.insert("Apples");
data.insert("apples");
std::copy(data.begin(), data.end(),
std::ostream_iterator<std::string>(std::cout, " - "));
std::cout << "\n";
}
因此,我們只將小寫值放入集合中:
> g++ pl.cpp
> ./a.out
apples -
>
class LCStringOriginalPreserved
{
std::string original;
std::string data;
public:
operator std::string&() {return data;}
operator std::string const&() const {return data;}
std::string& getOriginal() {return original;}
LCString(char const* init)
: original(init)
{
std::transform(original.begin(), original.end(),
std::back_inserter(data), &::tolower);
}
};
我更喜歡這個。
適用於Linux。
#include <strings.h>
#include <ctype.h>
#include <string>
#include <functional>
#include <tr1/functional_hash.h>
struct iequal_to : public std::binary_function <std::string,std::string,bool>
{
bool operator() (const std::string& x, const std::string& y) const
{
return (!strcasecmp(x.c_str(), y.c_str()));
}
};
const std::string LC(const std::string& x)
{
std::string ret(x);
std::string::size_type i;
for(i = 0; i < x.size(); ++i)
ret[i] = tolower(x[i]);
return ret;
}
struct ihash : public std::unary_function <std::string,size_t>
{
size_t ihash::operator() (const std::string& x) const
{
return std::tr1::hash<std::string>()(LC(x));
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.