std::unordered_map中使用std::vector<int>作为键
在这个例子中,使用了 std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>>
来存储每个组合的边长和夹角信息。这个时候,自定义哈希函数就会被用来计算 std::vector<int>
的哈希值,从而支持快速的插入和查找操作。
std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>> edgeMap;
// 当插入元素时:
std::vector<int> combo = {1, 2, 3, 4};
std::vector<double> edges = {1.0, 2.0, 3.0, 4.0};
std::vector<double> angles = {0.5, 0.5, 0.5, 0.5};
edgeMap[combo] = std::make_tuple(edges, angles, combo);
// 当查找元素时:
if (edgeMap.find(combo) != edgeMap.end()) {
auto [storedEdges, storedAngles, storedCombo] = edgeMap[combo];
// 使用 storedEdges, storedAngles, storedCombo
}
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>> toUnorderedMap(const std::map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>>& map) {
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>> unorderedMap;
for (const auto& entry : map) {
unorderedMap.insert(entry);
}
return unorderedMap;
}
报错:
[100%] Built target move_base_node In file included from /usr/include/c++/9/unordered_map:47, from /home/sukai/workspace/workspace_ros_car_noetic/src/trilateration/src/test/test4.cpp:7: /usr/include/c++/9/bits/unordered_map.h: In constructor ‘std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::unordered_map(_InputIterator, _InputIterator, std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type, const hasher&, const key_equal&, const allocator_type&) [with _InputIterator = __gnu_cxx::__normal_iterator<std::pair<std::vector<int>, std::pair<std::vector<double>, std::vector<int> > >*, std::vector<std::pair<std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > > >; _Key = std::vector<int>; _Tp = std::pair<std::vector<double>, std::vector<int> >; _Hash = std::hash<std::vector<int> >; _Pred = std::equal_to<std::vector<int> >; _Alloc = std::allocator<std::pair<const std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::size_type = long unsigned int; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::hasher = std::hash<std::vector<int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::key_equal = std::equal_to<std::vector<int> >; std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::allocator_type = std::allocator<std::pair<const std::vector<int>, std::pair<std::vector<double>, std::vector<int> > > >]’: /usr/include/c++/9/bits/unordered_map.h:174:30: error: use of deleted function ‘std::hash<std::vector<int> >::hash()’ 174 | const hasher& __hf = hasher(), | ^~~~~~~~
这个自定义哈希函数是用在 std::unordered_map
或 std::unordered_set
中,用于将 std::vector<int>
作为键来存储和查找值。这对于存储多边形的顶点组合特别有用,因为 std::vector<int>
默认没有提供哈希函数。
为了解决这个问题,需要手动定义一个哈希函数,并指定给 std::unordered_map
使用。下面是一个简单的哈希函数的示例:
namespace std {
template <>
struct hash<std::vector<int>> {
size_t operator()(const std::vector<int>& v) const {
size_t hash = 0;
for (int i : v) {
hash ^= std::hash<int>{}(i) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
}
还需要定义一个相等比较器来确保 std::unordered_map
正确工作。下面是一个简单的相等比较器的示例:
struct VectorIntEqual {
bool operator()(const std::vector<int>& a, const std::vector<int>& b) const {
return a == b;
}
};
然后,可以将这个相等比较器用作 std::unordered_map
的第四个模板参数。
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, std::hash<std::vector<int>>, VectorIntEqual> unorderedMap;
std::unordered_map<std::vector<int>, std::tuple<std::vector<double>, std::vector<double>, std::vector<int>>, VectorIntEqual> edgeMap;
// 当插入元素时:
std::vector<int> combo = {1, 2, 3, 4};
std::vector<double> edges = {1.0, 2.0, 3.0, 4.0};
std::vector<double> angles = {0.5, 0.5, 0.5, 0.5};
edgeMap[combo] = std::make_tuple(edges, angles, combo);
// 当查找元素时:
if (edgeMap.find(combo) != edgeMap.end()) {
auto [storedEdges, storedAngles, storedCombo] = edgeMap[combo];
// 使用 storedEdges, storedAngles, storedCombo
}
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual> toUnorderedMap(const std::map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual>& map) {
std::unordered_map<std::vector<int>, std::pair<std::vector<double>, std::vector<int>>, VectorIntEqual> unorderedMap;
for (const auto& entry : map) {
unorderedMap.insert(entry);
}
return unorderedMap;
}
在调用 toUnorderedMap
函数时,需要传递 VectorIntEqual
的实例作为第五个参数
auto unorderedMap = toUnorderedMap(map, VectorIntEqual{});
std::vector<std::string>
定义一个自定义哈希函数和相等比较器
-
定义哈希函数: 为
std::vector<std::string>
编写一个哈希函数。 -
定义相等比较器: 编写一个相等比较器来比较两个
std::vector<std::string>
是否相等。
下面是完整的代码示例,展示如何定义这些组件并使用 std::vector<std::string>
作为 std::unordered_map
的键:
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
// 定义哈希函数
namespace std {
template <>
struct hash<std::vector<std::string>> {
size_t operator()(const std::vector<std::string>& v) const {
size_t hash = 0;
for (const auto& str : v) {
hash ^= std::hash<std::string>{}(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
}
// 定义相等比较器
struct VectorStringEqual {
bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b) const {
return a == b;
}
};
int main() {
// 创建一个使用 vector<string> 作为键的 unordered_map
std::unordered_map<std::vector<std::string>, int, std::hash<std::vector<std::string>>, VectorStringEqual> myMap;
// 插入元素
std::vector<std::string> key1 = {"hello", "world"};
std::vector<std::string> key2 = {"foo", "bar"};
myMap[key1] = 1;
myMap[key2] = 2;
// 查找元素
if (myMap.find(key1) != myMap.end()) {
std::cout << "key1 found with value: " << myMap[key1] << std::endl;
} else {
std::cout << "key1 not found" << std::endl;
}
if (myMap.find(key2) != myMap.end()) {
std::cout << "key2 found with value: " << myMap[key2] << std::endl;
} else {
std::cout << "key2 not found" << std::endl;
}
return 0;
}
换一种:
// 自定义哈希函数和相等比较器
struct VectorStringHash {
std::size_t operator()(const std::vector<std::string>& vec) const {
std::size_t hash = 0;
for (const auto& str : vec) {
hash ^= std::hash<std::string>()(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
struct VectorStringEqual {
bool operator()(const std::vector<std::string>& lhs, const std::vector<std::string>& rhs) const {
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
}
};
std::unordered_map<std::vector<std::string>, std::vector<std::tuple<std::vector<double>, std::vector<std::vector<std::shared_ptr<ReflectorPanelPoint> >>>>,VectorStringHash, VectorStringEqual> unorderedEdgeMapNew_IdKey;
//增加数据:
unorderedEdgeMapNew_IdKey[std::vector<std::string>{point1->id, point2->id}].emplace_back(std::make_tuple(std::vector<double>{distance},std::vector<std::vector<std::shared_ptr<ReflectorPanelPoint>>>{{point1, point2}}));
//遍历数据:
// 遍历 unorderedEdgeMapNew_IdKey,打印数据
for (const auto& pair : unorderedEdgeMapNew_IdKey) {
std::cout << "Key: ";
for (const auto& str : pair.first) {
std::cout << str << " ";
}
std::cout << std::endl;
// 打印值
for (const auto& tuple : pair.second) {
const auto& innerVec1 = std::get<0>(tuple);
const auto& innerVec2 = std::get<1>(tuple);
std::cout << " Tuple - Vector 1: ";
for (const auto& value : innerVec1) {
std::cout << value << " ";
}
std::cout << std::endl;
std::cout << " Tuple - Vector 2: ";
for (const auto& innerVec : innerVec2) {
std::cout << "[ ";
for (const auto& ptr : innerVec) {
// 使用 ptr 指针
}
std::cout << "] ";
}
std::cout << std::endl;
}
}
//==========================================================
/*
#include <vector>
#include <unordered_map>
#include <tuple>
#include <cmath>
#include <iostream>
#include <queue>
#include <map>
//uuid
#include <chrono>
#include <random>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <thread>
#include <atomic>
#include <mutex>
//#include <algorithm> // 添加这一行以包含 std::sort
//#include <memory>
/**
*
* 通过两点中的边长匹配反光板id
* 可用递归
* @param edge1
* @param edge2
* @param threshold
* @return
*/
struct Point {
double x, y;
};
#ifndef REFLECTOR_PANEL_POINT_H
#define REFLECTOR_PANEL_POINT_H
class ReflectorPanelPoint {
public:
std::string id="EMPTY";//唯一标示
std::string shape="EMPTY";//CUBE:立方体(平面),CYLINDER: 圆柱体
std::string source_frame_id="map";//地图坐标系
std::string target_frame_id="base_link";//雷达坐标系
double range=0.0;
double intensity=0.0;
double x=0.0, y=0.0, z=0.0;
double rx=0.0, ry=0.0, rz=0.0, rw=1.0;
double scan_x=0.0, scan_y=0.0, scan_z=0.0;
double scan_rx=0.0, scan_ry=0.0, scan_rz=0.0, scan_rw=1.0;
double angle=0.0;//计算target_frame_id坐标系下的角度 scan_x=0.0, scan_y=0.0, scan_z
double distances=0.0;//计算target_frame_id坐标系下 rx=0.0, ry=0.0, rz=0.0, rw=1.0 欧几里德距离
//private:
// tf::TransformListener tf_listener;
//线程多
std::atomic<bool> should_stop{false}; // 用于线程停止的信号
std::thread transform_thread;
explicit ReflectorPanelPoint(const std::string& id);
explicit ReflectorPanelPoint(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw);
ReflectorPanelPoint();
~ReflectorPanelPoint() {
// stopTransformThread();
}
public:
static std::unordered_map<std::string, std::shared_ptr<ReflectorPanelPoint>> instances;
static std::mutex instance_mutex;
static std::shared_ptr<ReflectorPanelPoint> createInstance1(const std::string& id);
static std::shared_ptr<ReflectorPanelPoint> createInstance2(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw);
void startTransformThread(); // Assuming this function is defined elsewhere
void stopTransformThread();
// void transformAndCalculate(const ros::Time& time);
void transformThreadFunc();
friend std::ostream& printPoint(std::ostream& os,const std::shared_ptr<ReflectorPanelPoint> &point) {
//打印数据
// std::cout << "ReflectorPanelPoint shared_point1 :\n";
// printPoint(std::cout, shared_point1);
// std::cout << std::endl;
os << "ReflectorPanelPoint =》 "
<< ", ID: " << point->id << ", Shape: " << point->shape
<< ", Range: " << point->range << ", Intensity: " << point->intensity
<< ", source_frame_id: " << point->source_frame_id
<< ", source_Position: (" << point->x << ", " << point->y << ", " << point->z << ")"
<< ", source_Orientation: (" << point->rx << ", " << point->ry << ", " << point->rz << ", " << point->rw << ")"
<< ", target_frame_id: " << point->target_frame_id
<< ", target_Position: (" << point->scan_x << ", " << point->scan_y << ", " << point->scan_z << ")"
<< ", target_Orientation: (" << point->scan_rx << ", " << point->scan_ry << ", " << point->scan_rz << ", " << point->scan_rw << ")"
<< ", Angle: " << point->angle << ", Distances: " << point->distances;
return os;
}
//直接用 cout<<point<<打印
friend std::ostream& operator<<(std::ostream& os,const std::shared_ptr<ReflectorPanelPoint> &point) {
os << "ReflectorPanelPoint =》 "
<< ", ID: " << point->id << ", Shape: " << point->shape
<< ", Range: " << point->range << ", Intensity: " << point->intensity
<< ", source_frame_id: " << point->source_frame_id
<< ", source_Position: (" << point->x << ", " << point->y << ", " << point->z << ")"
<< ", source_Orientation: (" << point->rx << ", " << point->ry << ", " << point->rz << ", " << point->rw << ")"
<< ", target_frame_id: " << point->target_frame_id
<< ", target_Position: (" << point->scan_x << ", " << point->scan_y << ", " << point->scan_z << ")"
<< ", target_Orientation: (" << point->scan_rx << ", " << point->scan_ry << ", " << point->scan_rz << ", " << point->scan_rw << ")"
<< ", Angle: " << point->angle << ", Distances: " << point->distances;
return os;
}
};
#endif // REFLECTOR_PANEL_POINT_H
//--------------------------------------------------------------------------------------
// 在 .cpp 文件中定义静态成员变量
std::unordered_map<std::string, std::shared_ptr<ReflectorPanelPoint>> ReflectorPanelPoint::instances;
std::mutex ReflectorPanelPoint::instance_mutex;
ReflectorPanelPoint::ReflectorPanelPoint() {}
ReflectorPanelPoint::ReflectorPanelPoint(const std::string& id): id(id) {}
ReflectorPanelPoint::ReflectorPanelPoint(const std::string& id, double x, double y, double z, double rx, double ry, double rz, double rw):id(id), x(x), y(y), z(z), rx(rx), ry(ry), rz(rz), rw(rw) {}
// 初始化静态成员
std::shared_ptr<ReflectorPanelPoint> ReflectorPanelPoint::createInstance1(const std::string& id) {
std::lock_guard<std::mutex> lock(instance_mutex);
auto it = instances.find(id);
if (it == instances.end()) {
auto new_point = std::make_shared<ReflectorPanelPoint>(id);
instances[id] = new_point;
instances[id]->startTransformThread();
return new_point;
}
return it->second;
}
// 初始化静态成员
std::shared_ptr<ReflectorPanelPoint> ReflectorPanelPoint::createInstance2(const std::string& id, double x, double y, double z,double rx, double ry, double rz, double rw) {
std::lock_guard<std::mutex> lock(instance_mutex);
auto it = instances.find(id);
if (it == instances.end()) {
auto new_point = std::make_shared<ReflectorPanelPoint>(id, x, y, z, rx, ry, rz, rw);
instances[id] = new_point;
instances[id]->startTransformThread();
return new_point;
}
return it->second;
}
void ReflectorPanelPoint::startTransformThread() {
if (!transform_thread.joinable()) {
// transform_thread = std::thread(&ReflectorPanelPoint::transformThreadFunc, this);
}
}
void ReflectorPanelPoint::stopTransformThread() {
if (transform_thread.joinable()) {
should_stop.store(true);
transform_thread.join();
}
}
/**
void ReflectorPanelPoint::transformThreadFunc() {
while (!should_stop.load()) {
transformAndCalculate(ros::Time::now());
// 根据需要添加适当的延时,例如 10ms
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
void ReflectorPanelPoint::transformAndCalculate(const ros::Time& time) {
try {
// std::cout<<"111111111111111111111111111111111111111"<<std::endl;
// 获取从 source_frame_id 到 target_frame_id 的转换
tf::StampedTransform transform;
// 等待变换数据,最多等待1秒
tf_listener.waitForTransform(target_frame_id, source_frame_id,
ros::Time(0), ros::Duration(1.0));
tf_listener.lookupTransform(target_frame_id, source_frame_id, time, transform);
// 将坐标从 source_frame_id 转换到 target_frame_id
tf::Vector3 source_point(x, y, z);
tf::Vector3 target_point = transform * source_point;
// 计算欧几里得距离
distances = target_point.length();
// 计算角度
angle = atan2(target_point.y(), target_point.x());
// 设置旋转坐标
tf::Quaternion target_quaternion = tf::Quaternion(transform.getRotation());
scan_rx = target_quaternion.getX();
scan_ry = target_quaternion.getY();
scan_rz = target_quaternion.getZ();
scan_rw = target_quaternion.getW();
// 设置位置坐标
scan_x = target_point.x();
scan_y = target_point.y();
scan_z = target_point.z();
} catch (tf::TransformException& ex) {
ROS_ERROR("tf %s", ex.what());
}
}
*/
//=========================================================================================
// 简化的10位字符串生成器
std::string generate_shortened_string() {
// 获取当前时间(秒精度)
auto now = std::chrono::system_clock::now();
auto time_point_s = std::chrono::time_point_cast<std::chrono::seconds>(now);
uint32_t timestamp = time_point_s.time_since_epoch().count();
// 添加随机数
std::random_device rd;
std::mt19937 gen(rd());
// 产生一个0-25之间的随机数,对应字母'A'到'Z'
std::uniform_int_distribution<> letter_dis(0, 25);
char random_letter = 'A' + letter_dis(gen);
// 产生一个0-999999之间的随机数
std::uniform_int_distribution<> dis(0, 999999);
std::stringstream ss;//#include <sstream>
// 首字符为随机大写字母,后面跟上原本的5-5格式数字
ss << random_letter
<< std::uppercase << std::hex << std::setw(5) << std::setfill('0') << timestamp
<< std::hex << std::setw(5) << std::setfill('0') << dis(gen);
return ss.str();
}
//===========================================================================
**/
//====================================================================
在 std::unordered_map
中对比 std::vector<double>
的值,可以通过自定义的相等比较器来实现。这在标准库中是没有直接提供的,需要你自己实现。
下面是一个示例,其中 std::unordered_map
的键是 std::vector<std::string>
,值是 std::vector<double>
,并且包含自定义的哈希函数和相等比较器来对比 std::vector<double>
的值。
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <functional>
#include <cmath>
// 设定一个小的容忍值来
double equalDoubleThreshold_=1e-9;
// 定义哈希函数
namespace std {
template <>
struct hash<std::vector<std::string>> {
size_t operator()(const std::vector<std::string>& v) const {
size_t hash = 0;
for (const auto& str : v) {
hash ^= std::hash<std::string>{}(str) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
template <>
struct hash<std::vector<double>> {
size_t operator()(const std::vector<double>& v) const {
size_t hash = 0;
for (const auto& num : v) {
hash ^= std::hash<double>{}(num) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
}
// 定义相等比较器
struct VectorStringEqual {
bool operator()(const std::vector<std::string>& a, const std::vector<std::string>& b) const {
return a == b;
}
};
struct VectorDoubleEqual {
bool operator()(const std::vector<double>& a, const std::vector<double>& b) const {
if (a.size() != b.size()) return false;
for (size_t i = 0; i < a.size(); ++i) {
if (std::fabs(a[i] - b[i]) > equalDoubleThreshold_) return false; // 设定一个小的容忍值来比较浮点数
}
return true;
}
};
int main() {
// 创建一个使用 vector<string> 作为键,vector<double> 作为值的 unordered_map
std::unordered_map<std::vector<std::string>, std::vector<double>, std::hash<std::vector<std::string>>, VectorStringEqual> myMap;
// 插入元素
std::vector<std::string> key1 = {"hello", "world"};
std::vector<double> value1 = {1.0, 2.0, 3.0};
std::vector<std::string> key2 = {"foo", "bar"};
std::vector<double> value2 = {4.0, 5.0, 6.0};
myMap[key1] = value1;
myMap[key2] = value2;
// 查找元素并对比值
std::vector<double> targetValue = {1.0, 2.0, 3.0};
bool found = false;
for (const auto& pair : myMap) {
if (VectorDoubleEqual{}(pair.second, targetValue)) {
found = true;
std::cout << "匹配的键为: ";
for (const auto& str : pair.first) {
std::cout << str << " ";
}
std::cout << std::endl;
break;
}
}
if (!found) {
std::cout << "未找到匹配的值" << std::endl;
}
return 0;
}
在 std::unordered_map
中使用 std::vector<double>
作为键,需要自定义哈希函数和相等比较器。这些自定义类型用于计算 std::vector<double>
的哈希值,并定义两个 std::vector<double>
是否相等。以下是一个示例代码:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <cmath>
// 设定一个小的容忍值来
double equalDoubleThreshold_=1e-9;
// 定义哈希函数
namespace std {
template <>
struct hash<std::vector<double>> {
size_t operator()(const std::vector<double>& v) const {
size_t hash = 0;
for (const auto& num : v) {
hash ^= std::hash<double>{}(num) + 0x9e3779b9 + (hash << 6) + (hash >> 2);
}
return hash;
}
};
}
// 定义相等比较器
struct VectorDoubleEqual {
bool operator()(const std::vector<double>& a, const std::vector<double>& b) const {
if (a.size() != b.size()) return false;
for (size_t i = 0; i < a.size(); ++i) {
if (std::fabs(a[i] - b[i]) > equalDoubleThreshold_) return false; // 设定一个小的容忍值来比较浮点数
}
return true;
}
};
int main() {
// 创建一个使用 vector<double> 作为键,int 作为值的 unordered_map
std::unordered_map<std::vector<double>, int, std::hash<std::vector<double>>, VectorDoubleEqual> myMap;
// 插入元素
std::vector<double> key1 = {1.0, 2.0, 3.0};
int value1 = 10;
std::vector<double> key2 = {4.0, 5.0, 6.0};
int value2 = 20;
myMap[key1] = value1;
myMap[key2] = value2;
// 查找元素
std::vector<double> targetKey = {1.0, 2.0, 3.0};
auto it = myMap.find(targetKey);
if (it != myMap.end()) {
std::cout << "找到的值为: " << it->second << std::endl;
} else {
std::cout << "未找到匹配的键" << std::endl;
}
return 0;
}
现在,myMap使用double作为键,int作为值。哈希函数和相等比较器针对单个double进行了优化,请注意,使用这种方法可能会导致精度相关的意外行为,因为浮点数的哈希可能会受到浮点不精确性的影响。在某些情况下,两个看似相等的double可能会得到不同的哈希值。然而,在大多数简单场景下,这个实现应该足够用了。
// 定义哈希函数
namespace std {
template <>
struct hash<double> {
size_t operator()(const double& d) const {
return std::hash<long long>()(*reinterpret_cast<const long long*>(&d));
}
};
}
// 定义相等比较器
struct DoubleEqual {
bool operator()(const double& a, const double& b) const {
return std::fabs(a - b) <= equalDoubleThreshold_;
}
};
int main() {
// 创建一个使用 double 作为键,int 作为值的 unordered_map
std::unordered_map<double, int, std::hash<double>, DoubleEqual> myMap;
// 插入元素
double key1 = 1.0;
int value1 = 10;
double key2 = 4.0;
int value2 = 20;
myMap[key1] = value1;
myMap[key2] = value2;
// 查找元素
double targetKey = 1.0;
auto it = myMap.find(targetKey);
if (it != myMap.end()) {
std::cout << "找到的值为: " << it->second << std::endl;
} else {
std::cout << "未找到匹配的键" << std::endl;
}
return 0;
}
为了避免浮点不精确性导致的问题,可以使用一个基于字符串表示的哈希函数。这种方法将double转换为其文本表示,然后对字符串进行哈希。同时,比较器仍然使用绝对误差检查。以下是修改后的代码:
#include <iostream>
#include <unordered_map>
#include <cmath>
#include <sstream>
// 设定一个小的容忍值来
double equalDoubleThreshold_ = 1e-9;
// 定义哈希函数
namespace std {
template <>
struct hash<double> {
size_t operator()(const double& d) const {
std::ostringstream oss;
oss << d;
return std::hash<std::string>()(oss.str());
}
};
}
// 定义相等比较器
struct DoubleEqual {
bool operator()(const double& a, const double& b) const {
return std::fabs(a - b) <= equalDoubleThreshold_;
}
};
int main() {
// 创建一个使用 double 作为键,int 作为值的 unordered_map
std::unordered_map<double, int, std::hash<double>, DoubleEqual> myMap;
// 插入元素
double key1 = 1.0;
int value1 = 10;
double key2 = 4.0;
int value2 = 20;
myMap[key1] = value1;
myMap[key2] = value2;
// 查找元素
double targetKey = 1.0;
auto it = myMap.find(targetKey);
if (it != myMap.end()) {
std::cout << "找到的值为: " << it->second << std::endl;
} else {
std::cout << "未找到匹配的键" << std::endl;
}
return 0;
}
自定义double作为键,int作为值。哈希函数和相等比较器针对单个double进行了优化
#include <iostream>
#include <unordered_map>
#include <functional>
#include <cmath>
double equalDoubleDistanceThreshold_=0.1; // 1e-9
double equalDoubleAngleThreshold_=0.1;
// 自定义哈希函数
struct MyDoubleHash {
std::size_t operator()(const double& val) const {
// 你的自定义哈希算法
//return std::hash<std::string>()(std::to_string(val));
// return std::hash<long long>()(*reinterpret_cast<const long long*>(&val));
// 将double值四舍五入到给定的精度范围内,然后再进行哈希
// int roundedVal = static_cast<int>(std::round(val * 10)); // 例如,这里是保留一位小数
int roundedVal = static_cast<int>(std::round(val* 10 )); // 例如,这里是保留一位小数
return std::hash<int>()(roundedVal);
}
};
// 自定义比较器
struct MyDoubleEqual {
double threshold;
MyDoubleEqual(const double& t) : threshold(t) {}
bool operator()(const double& lhs, const double& rhs) const {
// 你的自定义比较逻辑
return std::fabs(lhs - rhs) < threshold; // 使用传递的阈值
}
};
int main() {
// 使用自定义哈希函数和比较器的unordered_map
// std::unordered_map<double, int, MyDoubleHash, MyDoubleEqual> myMap;
// 使用自定义哈希函数和比较器的unordered_map
std::unordered_map<double, int, MyDoubleHash, MyDoubleEqual> myMap(10, MyDoubleHash(), MyDoubleEqual(equalDoubleDistanceThreshold_));
// 插入一些值
// 插入一些值
myMap[3.14] = 1;
myMap[3.12159] = 9;
myMap[2.71828] = 2;
myMap[1.61803] = 3;
// 访问值
std::cout << "Value for 3.14159: " << myMap[3.14159] << std::endl;
std::cout << "Value for 2.71828: " << myMap[2.71828] << std::endl;
std::cout << "-------------------------------------" << std::endl;
// 测试比较器的效果
double key = 2.8183;
if (myMap.find(key) != myMap.end()) {
std::cout << "Found value for key: " << key <<" ,value: " <<myMap[key]<<std::endl;
} else {
std::cout << "error Value not found for " << key <<" ,value: " <<myMap[key]<< std::endl;
}
std::cout << "-------------------------------------" << std::endl;
// 使用范围 for 循环遍历所有数据
std::cout << "Using range-based for loop:" << std::endl;
for (const auto& pair : myMap) {
std::cout << "Key: " << pair.first << ", Value: " << pair.second << std::endl;
}
std::cout << "-------------------------------------" << std::endl;
// 使用迭代器遍历所有数据
std::cout << "\nUsing iterator:" << std::endl;
for (auto it = myMap.begin(); it != myMap.end(); ++it) {
std::cout << "Key: " << it->first << ", Value: " << it->second << std::endl;
}
std::cout << "-------------------------------------" << std::endl;
return 0;
}