简体   繁体   中英

How to map 2 keys (pair) to one key when the pair might not contain both values?

I want to map md5 to sha1 and sha256 to sha1.

Instead of using 2 different maps I thought of using std::map<pair<string, string>, string> . When inserting vlaues, I would have both md5 and sha256, but I can query only with md5 for exampe. Example :

md5= x;
map.find (x,null)--> return sha1
sha256 =y;
map.find ("" , y) --> return sha1
map(x,y) ----> return sha1

Is there any way of doing it?

some kind of OR between the keys..

Thanks a lot

I once created a class for a similar purspose maybe it could help you.

template<typename T, typename K1, typename K2>
class BiKeyMap
{
public:
    typedef boost::shared_ptr<T> ptr_type;

private:
    std::map<K1, ptr_type > _map1;
    std::map<K2, ptr_type > _map2;
public:

    bool insert(const ptr_type& value, const K1& key1, const K2& key2)
    {
        bool lResult1;
        bool lResult2;
        lResult1= _map1.insert(std::make_pair(key1, value)).second;
        lResult2= _map2.insert(std::make_pair(key2, value)).second;
        return (lResult1&&lResult2);
    }

    ptr_type find1(const K1& key)
    {
        typename std::map<K1, ptr_type>::iterator itr = _map1.find(key);
        if (itr == _map1.end())
            throw ...;
        return itr->second;
    }

    ptr_type find2(const K2& key)
    {
        typename std::map<K2, ptr_type>::iterator itr = _map2.find(key);
        if (itr == _map2.end())
           throw ....
        return itr->second;
    }

};

The problem is in the way the operator< is implemented between std::pair (that use lexicographic order between components, so that an empty string will always be "first").

Apart doing bad things like specialize operator< for std::pair<string,string> (that makes the new behavior available to any of such pairs even not involved in the map), you'll probably need as a key a class holding two strings, implementing operator< so that if one of the first members is empty the comparison is done only on the seconds.

like

struct mykey { std::string fisrt, std::string second; };

bool operator<(const mykey& a, const mykey& b)
{ 
    int ck = (a.first.size() && b.first.size()) + 2*(a.second.size() && b.second.size());
    return (ck==1)? a.first<b.first:
           (ck==2)? a.second<b.second:
           a.first+a.second < b.first+b.second; 
}

and providing a ctor like

mykey::mykey(const std::string s1, const std::string& s2) , so that you can create e "key to compare" by giving an empty string to s1 or s2, or insterting value in the map by giving both s1 and s2.

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