Sign in to follow this  

Is there any container for this?

This topic is 4860 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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[ I ] = Resource;
Map_Name2Resource[ Name ] = Resource;
Map_Resource2IDName[ Resource ] = pair( I , Name );
}
void Unregister( int I )
{
CResource * Resource = Map_ID2Resource[ I ];
std::string Name = Map_Resource2IDName[ Resource ].second;
Map_ID2Resource.remove( I );
Map_Name2Resource.remove( Name );
Map_Resource2IDName.remove( Resource );
}
void Unregister( const std::string & Name )
{
CResource * Resource = Map_Name2Resource[ Name ];
int I = Map_Resource2IDName[ Resource ].first;
Map_ID2Resource.remove( I );
Map_Name2Resource.remove( Name );
Map_Resource2IDName.remove( Resource );
}
void Unregister( CResource * Resource )
{
int I = Map_Resource2IDName[ Resource ].first;
std::string Name = Map_Resource2IDName[ Resource ].second;
Map_ID2Resource.remove( I );
Map_Name2Resource.remove( Name );
Map_Resource2IDName.remove( Resource );
}
CResource * Lookup( const std::string & Name )
{
return Map_Name2Resource[ Name ];
}
CResource * Lookup( int I )
{
return Map_ID2Resource( I );
}
};



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.

edit: [ code ] -> [ source ]

[Edited by - MaulingMonkey on August 27, 2004 1:22:21 PM]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by HexDump
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 :?.


In case you haven't noticed, I've pointed you to a library that solves that problem. So no, you're not the first one ever to need that.

Share this post


Link to post
Share on other sites
Quote:
Original post by jjmontes
But a hash function doesn't guarantee that its result is unique for each key. Otherwise, it wouldn't be a hash function.

Hash to a 64 bit value with a decent hash function and it's unique for all practical purposes even if it's not guaranteed unique. Even hashing to a 32 bit value should be sufficient for most games.

Share this post


Link to post
Share on other sites
Quote:
Original post by mattnewport
Quote:
Original post by jjmontes
But a hash function doesn't guarantee that its result is unique for each key. Otherwise, it wouldn't be a hash function.

Hash to a 64 bit value with a decent hash function and it's unique for all practical purposes even if it's not guaranteed unique. Even hashing to a 32 bit value should be sufficient for most games.


Hell, but still it isn't guaranteed. You can't make an application rely on it beeing "unique for all practical purposes even if it's not guaranteed unique".

In any case, it would depend on the hash funcion chosen. Some perform well for certain uses (for example, hashing unicode strings) but bad for other uses (for example, hashing gene sequences in two-bits per gen format).

Share this post


Link to post
Share on other sites

This topic is 4860 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this