创建 boost::tuple<std::string, std::string, int> 和 std::vector<int> 的映射
Posted
技术标签:
【中文标题】创建 boost::tuple<std::string, std::string, int> 和 std::vector<int> 的映射【英文标题】:Creating map of boost::tuple<std::string, std::string, int>and std::vector<int> 【发布时间】:2014-03-15 09:47:03 【问题描述】:我想用 Key 作为两个字符串和一个 int 的组合来创建映射,并且 value 可以是基于 key 的多个 int。 所以我尝试创建 boost::tuple 和 std::vector 的映射。我尝试为此编写示例程序,如下所示:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <string>
#include <boost/tuple/tuple.hpp>
#include <boost/unordered_map.hpp>
using namespace std;
typedef boost::tuple<std::string, std::string, int> tpl_t;
struct key_hash : public std::unary_function<tpl_t, std::size_t>
std::size_t operator()(const tpl_t& k) const
return boost::get<0>(k)[0] ^ boost::get<1>(k)[0] ^ boost::get<2>(k);
;
struct key_equal : public std::binary_function<tpl_t, tpl_t, bool>
bool operator()(const tpl_t& v0, const tpl_t& v1) const
return (
boost::get<2>(v0) == boost::get<2>(v1) &&
boost::get<0>(v0) == boost::get<0>(v1) &&
boost::get<1>(v0) == boost::get<1>(v1)
);
;
typedef boost::unordered_map<tpl_t, std::vector<int>, key_hash,key_equal> map_t;
void function1(map_t& myMap, std::string file, std::string txt, int num1, int num2)
tpl_t key = boost::make_tuple(file, txt, num1);
map_t::iterator itr = myMap.find(key);
if(itr != myMap.end())
itr->second.push_back(num2);
else
std::vector<int> num2Vec;
num2Vec.push_back(num2);
myMap.insert(std::make_pair(boost::make_tuple(file,txt,num1),num2Vec));
int main()
map_t myMap;
function1(myMap, "file1", "text", 5, 10);
function1(myMap, "file1", "text_t", 5, 30);
function1(myMap, "file2", "text", 5, 50);
这个程序运行良好,但我想知道是否有更好的方法来做到这一点。我担心性能,因为地图的大小可以增长到任何东西。不过我还没有衡量性能。
谢谢, 史瑞克
【问题讨论】:
去掉#include "stdafx.h" 【参考方案1】:我担心性能,因为地图的大小可能会增长到任何东西。不过我还没有衡量性能。
在担心您的设计可能不适合该任务之前,您应该先担心是否有适当的性能测量。
设计多个用例,并创建示例数据分布 - 组合键和值的常见情况、每边的标准差和尾部。不仅要考虑数据集本身,还要考虑其设置和使用配置文件 - 插入、搜索、删除的频率。
也就是说,总体而言,您将复合键建模为元组的方法是明智的,尽管主观上我更喜欢结构,但这是一个非常小的评论。
对于值 - 考虑使用 multi-map 而不是带有矢量的地图,这可能会更快,但这取决于值的数量。
这里还有一些需要考虑的事情:
您的(多)地图是否必须有序,还是可以保持无序?根据使用情况,无序地图可能会明显更快。 您能否调整您对键的了解以更快地进行比较?例如,如果字符串很长且是静态的(例如,几乎总是“file1”),您是否可以通过先评估两个比较键的整数部分来受益? 您是否可以通过使用分层映射而不是使用复合键的映射来受益?最好用样本数据和场景来回答上述许多问题,这些数据和场景构成了您程序的测试套件的一部分。这样,您可以在更改数据结构时观察性能的变化。
【讨论】:
非常感谢您的建议。当然我在第一次实施时错过了这些要点。我不想在我的地图中出现重复的键,如果键相同,我想填充相应的向量,所以我使用的是地图而不是多地图。我不清楚你提到的分层地图的概念。请查看修改后的实现,并让我知道您对此的看法。感谢您的宝贵时间。 @shirk 我相信一元/二元函数已被弃用,无需从它们继承——它们只是添加了几个 typedef。此外,我认为您的key_hash
可能不太适合作为哈希值。你最好在成员上使用boost::hash_combine
或boost::hash
。见boost.org/doc/libs/1_55_0/doc/html/hash/combine.html
@shirk 您可以使用equal_range
获取与某个键对应的所有值的列表,这可能是也可能不是您所追求的(例如,这些值在内存,这很重要),但在任何情况下,您都需要根据指向值向量的唯一键来评估它。
谢谢,我尝试了使用 boost:hash_combine() 的建议。现在,我创建了带有 operator== 和 hash_value() 的结构,而不是元组。请参阅实现http://codepad.org/XDEMPLek。非常感谢,因为我正在学习 boost 的所有这些新功能:)以上是关于创建 boost::tuple<std::string, std::string, int> 和 std::vector<int> 的映射的主要内容,如果未能解决你的问题,请参考以下文章