不区分大小写的STL容器(例如std :: unordered_set)

时间:2011-12-25 00:50:10

标签: c++ stl case-insensitive

制作std :: unordered_set CASE-INSENSITIVE容器的最短,最跨平台方式是什么?

my_set.insert("Apples");  
my_set.insert("apples"); //Insert doesn't occur because of duplicate item

我知道STL提供哈希 Pred 哈希应该是什么? Pred 应该是什么?如果它们不是内置的,那么请提供它们的代码以及它们的使用示例(即如何声明std::unordered_set?)。

由于批评,我将详细阐述我想要做的事情。我需要一个高性能的透明HTTP代理服务器,它所做的一件事就是快速查找HTTP头字段。 HTTP标头字段被定义为不区分大小写,因此我需要一个不区分大小写的容器。

3 个答案:

答案 0 :(得分:12)

unordered_set的定义是

  template <class Value,
            class Hash = hash<Value>,
            class Pred = std::equal_to<Value>,
            class Alloc = std::allocator<Value> >
  class unordered_set;

如果您提供不区分大小写的哈希 Pred 仿函数,那么该组也会变得如此。

这是一个简单的示例,字符串 hash function is simplisti c ,但您可以根据需要进行更改

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

答案 1 :(得分:1)

我个人会定义一个不区分大小写的值类型,并在最小的提示下转换为字符串。因此允许我使用标准的哈希和谓词模型。

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

答案 2 :(得分:-1)

我更喜欢这个。

适用于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));
  }
};