使用自定义哈希函数插入unordered_set [英] Inserting into an unordered_set with custom hash function

查看:138
本文介绍了使用自定义哈希函数插入unordered_set的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码来制作 unordered_set< Interval>

  struct Interval {
unsigned int begin;
unsigned int end;
bool已更新; //如果是concat,则为true。最初是错误的
int patternIndex; //模式索引。对于单一模式
int proteinIndex有效; //蛋白质指数。用于检索模式
};

struct Hash {
size_t operator()(const Interval& interval);
};

size_t Hash :: operator()(const Interval& interval){
string temp = to_string(interval.begin)+ to_string(interval.end)+ to_string(interval.proteinIndex) ;
return hash< string>()(temp);
}

unordered_set< Interval,string,Hash>测试;

但是,当我尝试使用以下代码插入时,我无法编译:

  for(list< Interval> :: iterator i = concat.begin(); i!= concat.end(); ++ i){
test.insert((* i));
}

此外,例如,我无法从错误消息中确定问题出在哪里:

 注意:候选对象是:
注意:size_t Hash :: operator()(const Interval&)
注意:候选人期望1个论点,2个提供了

我以为我只提供了1个论点...



我的插入代码有什么问题?






这是新的实例化代码: unordered_set< Interval,Hash>测试;
但是,我仍然收到大量错误消息,例如:

 注释:候选者是:
注释:size_t Hash :: operator()(const Interval&)< near match>
注意:隐式'this'参数从'const Hash *'到'Hash *'的未知转换


解决方案

第一个问题



您正在传递字符串作为实例化 unordered_set<> 类模板的第二个模板参数。 第二个参数应为哈希函子的类型,并为 std ::字符串不是可调用对象。



也许打算写:

  unordered_set< Interval,/ *字符串* /哈希>测试; 
// ^^^^^^^^^^^^^
//为什么?

此外,我建议使用开始 end ,因为它们是C ++标准库的算法名称。



第二个问题:



请记住散列函数应限定为 const ,因此您的函子应为:

  struct Hash {
size_t operator()(const Interval& interval)const {
// ^^^^^
//不要忘记这一点!
字符串温度= to_string(interval.b)+
to_string(interval.e)+
to_string(interval.proteinIndex);
返回(temp.length());
}
};

第三个问题:



最后,如果您希望 std :: unordered_set 能够处理间隔 Interval 类型的对象,您需要定义一个与哈希函数一致的相等运算符。默认情况下,如果您没有将任何类型参数指定为 std :: unordered_set 类模板的第三个参数,则 operator == 将被使用。



您的班级目前没有 operator == 的任何重载时间间隔,因此您应该提供一个。例如:

 内联布尔运算符==(时间间隔const& lhs,时间间隔const& rhs)
{
return(lhs.b == rhs.b)&&
(lhs.e == rhs.e)&&
(lhs.proteinIndex == rhs.proteinIndex);
}

结论:



在完成所有上述修改后,您可以在此在线示例中看到您的代码正在编译。 / p>

I have the following code to make an unordered_set<Interval>. This compiles fine.

struct Interval {
  unsigned int begin;
  unsigned int end;
  bool updated;   //true if concat.  initially false
  int patternIndex;  //pattern index. valid for single pattern
  int proteinIndex;   //protein index.  for retrieving the pattern
};

struct Hash {
  size_t operator()(const Interval &interval);
};

size_t Hash::operator()(const Interval &interval){
  string temp = to_string(interval.begin) + to_string(interval.end) + to_string(interval.proteinIndex);
  return hash<string>()(temp);
}

unordered_set<Interval, string, Hash> test;

However, I cannot compile when I try to insert using this code:

for(list<Interval>::iterator i = concat.begin(); i != concat.end(); ++i){
  test.insert((*i));
}

Moreover, I cannot determine what the problem is from the error messages, for example:

note: candidate is:
note: size_t Hash::operator()(const Interval&)
note:   candidate expects 1 argument, 2 provided  

I thought I only provided 1 argument...

What is the problem with my insertion code?


Here's the new instantiation code: unordered_set<Interval, Hash> test; However, I'm still receiving a slew of error messages, for example:

note: candidate is:
note: size_t Hash::operator()(const Interval&) <near match>
note:   no known conversion for implicit ‘this’ parameter from ‘const Hash*’ to ‘Hash*’

解决方案

First problem:

You are passing string as the second template argument for your instantiation of the unordered_set<> class template. The second argument should be the type of your hasher functor, and std::string is not a callable object.

Perhaps meant to write:

unordered_set<Interval, /* string */ Hash> test;
//                      ^^^^^^^^^^^^
//                      Why this?

Also, I would suggest using names other than begin and end for your (member) variables, since those are names of algorithms of the C++ Standard Library.

Second problem:

You should keep in mind, that the hasher function should be qualified as const, so your functor should be:

struct Hash {
   size_t operator() (const Interval &interval) const {
   //                                           ^^^^^
   //                                           Don't forget this!
     string temp = to_string(interval.b) + 
                   to_string(interval.e) + 
                   to_string(interval.proteinIndex);
     return (temp.length());
   }
};

Third problem:

Finally, if you want std::unordered_set to be able to work with objects of type Interval, you need to define an equality operator consistent with your hash function. By default, if you do not specify any type argument as the third parameter of the std::unordered_set class template, operator == will be used.

You currently do not have any overload of operator == for your class Interval, so you should provide one. For example:

inline bool operator == (Interval const& lhs, Interval const& rhs)
{
    return (lhs.b == rhs.b) && 
           (lhs.e == rhs.e) && 
           (lhs.proteinIndex == rhs.proteinIndex); 
}

Conclusion:

After all the above modifications, you can see your code compiling in this live example.

这篇关于使用自定义哈希函数插入unordered_set的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆