Is there any container for this?

Started by
11 comments, last by jjmontes 19 years, 7 months ago
Hello, I have some resources I need to address by ID (integer) and name (string). I have thought of using stl::hashmaps but they only allow a key. Is there any other way to do this?. I have think about using two hashmaps but then, it is a bit tricky when removing elements from the hashmaps. Thanks in advance, HexDump.
Advertisement
How about a map?
You might be able to use a std::map, and use a std::pair<int, std::string> as the key. I think the comparison operators for the std::pair type should be enough for the map to sort and retrieve based on the key.
std::map<std::pair<int, std::string>, t_Resource> Map;

You might want to make some typedefs to simplify things though. Iterators and such are gonna be kinda messy, being a std::pair containing a std::pair and a resource.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
If you're ok with using development code, Boost has a multi-index container library in CVS.

Of course, if it's not urgent, you could just wait until they actually release it. [grin]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:Original post by HexDump
Hello,


I have some resources I need to address by ID (integer) and name (string). I have thought of using stl::hashmaps
but they only allow a key. Is there any other way to do this?. I have think about using two hashmaps but then, it is a bit tricky when removing elements from the hashmaps.


Thanks in advance,
HexDump.


No need for removals to be tricky...


class CResourceMap
{
std::map< int , CResource * > Map_ID2Resource;
std::map< std::string , CResource * > Map_Name2Resource;;
std::map< CResource * , std::pair< int , std::string > > Map_Resource2IDName;
public:
void Register( int I , const std::string & Name , CResource * Resource )
{
Map_ID2Resource = Resource;<br> Map_Name2Resource[ Name ] = Resource;<br> Map_Resource2IDName[ Resource ] = pair( I , Name );<br> }<br> <span class="cpp-keyword">void</span> Unregister( <span class="cpp-keyword">int</span> I )<br> {<br> CResource * Resource = Map_ID2Resource;<br> std::string Name = Map_Resource2IDName[ Resource ].second;<br> Map_ID2Resource.remove( I );<br> Map_Name2Resource.remove( Name );<br> Map_Resource2IDName.remove( Resource );<br> }<br> <span class="cpp-keyword">void</span> Unregister( <span class="cpp-keyword">const</span> std::string &amp; Name )<br> {<br> CResource * Resource = Map_Name2Resource[ Name ];<br> <span class="cpp-keyword">int</span> I = Map_Resource2IDName[ Resource ].first;<br> Map_ID2Resource.remove( I );<br> Map_Name2Resource.remove( Name );<br> Map_Resource2IDName.remove( Resource );<br> }<br> <span class="cpp-keyword">void</span> Unregister( CResource * Resource )<br> {<br> <span class="cpp-keyword">int</span> I = Map_Resource2IDName[ Resource ].first;<br> std::string Name = Map_Resource2IDName[ Resource ].second;<br> Map_ID2Resource.remove( I );<br> Map_Name2Resource.remove( Name );<br> Map_Resource2IDName.remove( Resource );<br> }<br> CResource * Lookup( <span class="cpp-keyword">const</span> std::string &amp; Name )<br> {<br> <span class="cpp-keyword">return</span> Map_Name2Resource[ Name ];<br> }<br> CResource * Lookup( <span class="cpp-keyword">int</span> I )<br> {<br> <span class="cpp-keyword">return</span> Map_ID2Resource( I );<br> }<br>};<br><br></pre></div><!–ENDSCRIPT–><br><br>I'm curious, however, why you need two indexes. You'd probably want to templatize the above class, and replace the Map_Resource2IDName definition with a pair of iterators instead of the actual lookups.<br><br>edit: -&gt; [ source ]<br><br><!--EDIT--><span class=editedby><!--/EDIT-->[Edited by - MaulingMonkey on August 27, 2004 1:22:21 PM]<!--EDIT--></span><!--/EDIT-->
And since I was bored, the templatized version:

template < typename IndexT1 , typename IndexT2 , typename BaseType > class DualMap{    typedef std::hash_map< IndexT1 , BaseType * > TMap1;    typedef std::hash_map< IndexT2 , BaseType * > TMap2;    TMap1 Map_T12Resource;    TMap2 Map_T22Resource;    std::hash_map< BaseType * , std::pair< TMap1::iterator , TMap2::iterator > > Map_Base2Types;public:    void Register( const IndexT1 & I1 , const IndexT2 & I2 , const BaseType * Resource )    {        TMap1::iterator I1Iterator = Map_T12Resource.insert( I1 ).first;        *I1Iterator = Resource;        TMap2::iterator I2Iterator = Map_T22Resource.insert( I2 ).second;        *I2Iterator = Resource;        Map_Base2Types[ Resource ] = pair( I1Iterator , I2Iterator );    }    void Unregister( const BaseType * Resource )    {        Map_T12Resource.remove( Map_Base2Types[ Resource ].first );        Map_T22Resource.remove( Map_Base2Ttpes[ Resource ].second );        Map_Base2Types.remove( Resource );    }    void Unregister( const IndexT1 & Index )    {        BaseType * Resource = Map_T12Resource[ Index ];    }    void Unregister( const IndexT2 & Index )    {        BaseType * Resource = Map_T22Resource[ Index ];    }    BaseType * Lookup ( const IndexT1 & Index ) const    {        return Map_T12Resource[ Index ];    }    BaseType * Lookup ( const IndexT2 & Index ) const    {        return Map_T22Resource[ Index ];    }};


Warning: untested ^_^

edit: typeo

[Edited by - MaulingMonkey on August 27, 2004 2:54:20 PM]
Is the ID pre-determined or can it be arbitrary as long as it's unique? If you can set the ID to anything you want just use the hash of the name string as the ID and then use a container with a single integer key that is the hashed ID.

Game Programming Blog: www.mattnewport.com/blog

Well, I need 2 indexes because I coudl want to get/set a resource or something by id or name. No one has had this problem before :?. Perhaps I´m doing something wrong.


HexDUmp
Oh, ID OR name. Ignore my comments, then. I was totally thinking ID and name together as a key.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Quote:Original post by mattnewport
Is the ID pre-determined or can it be arbitrary as long as it's unique? If you can set the ID to anything you want just use the hash of the name string as the ID and then use a container with a single integer key that is the hashed ID.


But a hash function doesn't guarantee that its result is unique for each key. Otherwise, it wouldn't be a hash function.

-=[ J ]=-I always forget to change the tagline.

This topic is closed to new replies.

Advertisement