简体   繁体   中英

Creating map of boost::tuple<std::string, std::string, int>and std::vector<int>

I want to create map with Key as a combination of two strings and one int and value can be multiple ints based on key. So I tried to create map of boost::tupleand std::vector. I tried writing sample program for this like below:

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

This program is working fine but I want to know if there is any better way to do this. I am worried about performance as size of map can grow to anything. I have not measured performance though.

Thanks,
Shrik

I am worried about performance as size of map can grow to anything. I have not measured performance though.

You should worry about having a performance measurement in place before you worry about the eventuality of your design being unsuitable for the task.

Design a number of use cases, and create a sample data distribution - the common cases for composite keys and values, a standard deviation to each side, and the tails. Consider not only the data set itself but also its setup and use profile - the frequency of inserts, searches, removals.

That said, overall your approach of modelling the composite key as a tuple is sensible, although, subjectively, I'd prefer a struct instead, but that's a very minor comment.

For the values - consider using a multi-map instead of a map with a vector, this will likely to be faster, but it depends on the number of values.

Here are a couple more things to consider:

  • Does your (multi-)map have to be ordered or can it remain unordered? Depending on the use profile, an unordered map could be significantly faster.
  • Could you tailor your knowledge of the keys to make comparisons faster? For example, if the strings are long and static (eg, almost always "file1"), could you benefit by evaluating the integer part of two compared key first?
  • Could you benefit by having a hierarchical map instead of a map with a composite key?

It's better to have many of the questions above answered with sample data and scenarios which form part of the test suite for your program. That way you can observe the changes to performance as you change your data structures.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM