我有2个元素(现在)map:
#define IDI_OBJECT_5001 5001
#define IDI_OBJECT_5002 5002
/.../
ResourcesMap[IDI_OBJECT_5001] = "path_to_png_file1";
ResourcesMap[IDI_OBJECT_5002] = "path_to_png_file2";
我正在尝试实现搜索此地图的方法。我正在传递字符串参数(文件路径)和方法返回int(映射的键值)
int ResFiles::findResForBrew(string filePath)
{
string value = filePath;
int key = -1;
for (it = ResourcesMap.begin(); it != ResourcesMap.end(); ++it)
{
if (/*checking if it->second == value */)
{
key = it->first;
break;
}
}
return key;
}
类ResFiles { 上市: ResFiles(); 〜ResFiles();
map <int, string> ResourcesMap;
map <int, string>::const_iterator it;
void filenamesForBrew();
int findResForBrew(string filePath);
private:
};
我如何检查它 - >&gt; second-&gt; == value,然后返回那个键? 我会感激一些帮助。提前谢谢。
答案 0 :(得分:2)
这是一个基本的实现
template <typename K, typename V>
K keyFor(std::map<K, V> const& map, V const& target)
{
for (typename std::map<K, V>::const_iterator it=map.begin(); it!=map.end(); ++it)
if (it->second == target)
return it->first;
return K(); // or throw?
}
或者,支持C ++ 11:
for (auto& pair : map)
if (pair.second == target)
return pair.first;
答案 1 :(得分:1)
你正在做什么应该工作,(只是it->second ==value
)虽然如果你想要一个“有效”的查找键值,你应该创建第二张地图。
有些std::find
这样的算法需要一个特殊的谓词,但它们只是在下面使用一个循环并且效率不高,因为搜索仍然是线性的。
如果你想做很多事情(如果你是......那就问你的设计)并想要一个特殊的模板,你可以:
template< typename K, typename V >
bool findByValue( std::map<K,V> const& theMap, K& key, const V& value )
{
typename std::map<K,V>::const_iterator iter;
for( iter it = theMap.begin(), itEnd = theMap.end(); it != itEnd; ++it )
{
if( it->second == value )
{
key = iter->first;
return true;
}
}
return false;
}
或者是std :: find_if
的自定义谓词template< typename P >
class Match2nd
{
typedef typename P::second_type value_type;
value_type val;
public:
explicit Match2nd( value_type const& v ) : val( v )
{
}
bool operator()( P const& p ) const
{
return p.second == val;
}
};
template< typename M >
Match2nd< typename M::value_type >
makeMatch2nd( const M& map, typename M::mapped_type const& v )
{
return Match2nd< M::value_type >( v );
}
然后在你的代码中你可以:
std::map< int, std::string >::const_iterator iter =
std::find_if( ResourcesMap.begin(), ResourcesMap.end(), makeMatch2nd( value ) );
// if iter is end() the key doesn't exist,
//if it does then iter->first is your key
你当然可以把它变成一个功能..
使用C ++ 0x,您还可以将Match2nd放入lambda并放入std :: find。然而...
所有这些东西仍然是线性搜索。如果您的地图很大,请以其他方式放入地图或使用boost :: multi_index或类似地方。
答案 2 :(得分:0)
好的,我找到了:
int ResFiles::findResForBrew(string filePath)
{
string value = filePath;
int key = -1;
for (it = ResourcesMap.begin(); it != ResourcesMap.end(); ++it)
{
if(it->second.compare(filePath) == 0)
{
key = it->first;
break;
}
}
return key;
}
答案 3 :(得分:0)
首先,如果你的Key是路径,为什么要按ID索引?
如果您要查看文件路径,请将其用作Key,对于地图的每个键,查找某个值会比迭代更快。
第二个,恕我直言我建议使用const值而不是#define
s,#define
s没有输入所以如果执行一些意外的数据转换会很麻烦,我是一个强大价值类型的忠实粉丝。
试试这个:
// The type of the ID of the Resources.
typedef int ObjectID;
// Current resources.
const ObjectID IDI_OBJECT_5001 = 5001;
const ObjectID IDI_OBJECT_5002 = 5002;
// The type of a map containing resources, you can assure that
// a Resource ID would be stored, as you can see at the mapped type.
typedef std::map<const std::string, const ObjectID> idpath;
idpath ResourcesMap;
第三,我不鼓励使用map::operator[]
插入值,调用此运算符创建空对象,然后通过{{1}分配新值映射类型;更不用说如果对象已经存在,则被覆盖。因此,使用此运算符我认为您执行的操作多于使用operator=
方法:
map::insert
所以,最后,在你的代码中做什么:
ResourcesMap.insert(idpath::value_type("path_to_png_file1", IDI_OBJECT_5001));
ResourcesMap.insert(idpath::value_type("path_to_png_file2", IDI_OBJECT_5002));
请记住,此算法假设您可以交换Key-Map对,否则,您需要迭代整个地图。