Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C++;map,有没有办法搜索给定值的键? C++中的代码> STD::MAP< /Cord>,有没有办法搜索映射值的键?例如:_C++ - Fatal编程技术网

在C++;map,有没有办法搜索给定值的键? C++中的代码> STD::MAP< /Cord>,有没有办法搜索映射值的键?例如:

在C++;map,有没有办法搜索给定值的键? C++中的代码> STD::MAP< /Cord>,有没有办法搜索映射值的键?例如:,c++,C++,我有这张地图: map<int,string> myMap; myMap[0] = "foo"; 不,不是直接的 一种选择是检查地图中的每个值,直到找到要查找的内容。显然,这将是O(n) 为此,您可以编写一个for()循环,或者使用std::find_if()。为了使用find_if(),您需要创建一个谓词。在C++11中,这可能是一个lambda: typedef std::map <unsigned, Student> MyMap; MyMap myMap; /

我有这张地图:

map<int,string> myMap;
myMap[0] = "foo";
不,不是直接的

一种选择是检查地图中的每个值,直到找到要查找的内容。显然,这将是O(n)

为此,您可以编写一个
for()
循环,或者使用
std::find_if()
。为了使用
find_if()
,您需要创建一个谓词。在C++11中,这可能是一个lambda:

typedef std::map <unsigned, Student> MyMap;
MyMap myMap; 

// ...

const string targetName = "Jones";
find_if (myMap.begin(), myMap.end(), [&targetName] (const MyMap::value_type& test)
{
  if (test.second.mName == targetName)
    return true;
});
typedef std::map MyMap;
我的地图;
// ...
常量字符串targetName=“Jones”;
查找(myMap.begin()、myMap.end()、[&targetName](常量myMap::value_类型和测试)
{
if(test.second.mName==targetName)
返回true;
});
如果您使用的是C++03,那么这可能是一个函子:

struct MatchName
: public std::unary_function <bool, MyMap::value_type>
{
  MatchName (const std::string& target) : mTarget (target) {}
  bool operator() (const MyMap::value_type& test) const
  {
    if (test.second.mName == mTarget)
      return true;
    return false;
  }
private:
  const std::string mTarget;
};


// ...

find_if (myMap.begin(), myMap.end(), MatchName (target));
struct MatchName
:公共标准::一元函数
{
MatchName(const std::string和target):mTarget(target){}
bool运算符()(常量MyMap::value_type&test)常量
{
if(test.second.mName==mTarget)
返回true;
返回false;
}
私人:
常量std::字符串mTarget;
};
// ...
查找_if(myMap.begin()、myMap.end()、MatchName(target));
另一个选择是建立索引。索引可能是另一个映射,其中键是您想要查找的任何值,值是返回主映射的某种索引

假设您的主地图包含
Student
对象,这些对象由名称和其他内容组成,而此地图中的键是Student ID,一个整数。如果要查找具有特定姓氏的学生,可以构建索引映射,其中键为姓氏(可能希望在此处使用
multimap
),值为学生ID。然后可以索引回主映射以获取
student
的其余属性


第二种方法存在挑战。添加或删除元素时,必须保持主地图和索引(或标记)同步。您必须确保您选择的索引作为索引中的值不会发生任何变化,例如指针。如果您是多线程的,那么您必须考虑如何在不引入死锁或竞争条件的情况下保护映射和索引。

我能想到的实现这一点的唯一方法是对其进行迭代。这很可能不是你想要的,但这是我能想到的最好的机会。祝你好运

std::map
不提供(快速)方法来查找给定值的键

你想要的通常被称为“双射映射”,或者简称为“双射映射”。这通常是通过使用两个“粘合”在一起的索引树来实现的(其中
std::map
只有一个索引树用于键)

如果您不想使用Boost,如果存储不是一个大问题,并且如果您可以支持额外的代码工作,那么您可以简单地使用两个映射并手动将它们粘合在一起:

std::map<int, string> myMapForward;
std::map<string, int> myMapBackward;    // maybe even std::set

// insertion becomes:
myMapForward.insert(std::make_pair(0, "foo"));
myMapBackward.insert(std::make_pair("foo", 0));

// forward lookup becomes:
myMapForwar[0];

// backward lookup becomes:
myMapBackward["foo"];
std::映射myMapForward;
std::map myMapBackward;//甚至可能是std::set
//插入变为:
插入(std::make_pair(0,“foo”);
插入(std::make_pair(“foo”,0));
//正向查找变为:
myMapForwar[0];
//反向查找变为:
myMapBackward[“foo”];
当然,您可以将这两个映射封装在一个类中,并提供一些有用的接口,但这可能有点过分,并且使用两个具有相同内容的映射无论如何都不是可选的解决方案。如下所述,异常安全也是此解决方案的一个问题。但在许多应用程序中,只需添加另一个反向映射就足够了

请注意,由于
std::map
存储唯一的键,这种方法将只支持向后查找唯一的值,因为前向映射的值空间中的冲突对应于后向映射的键空间中的冲突。

您可以通过迭代来实现,这将花费
O(n)时间
。或者您可以存储将占用
O(n)空间的反向映射

通过迭代:

std::map<int, string> fmap;

for (std::map<int,string>::iterator it=fmap.begin(); it!=fmap.end(); ++it)
    if (strcmp(it->second,"foo"))
        break;
std::map-fmap;
对于(std::map::iterator it=fmap.begin();it!=fmap.end();++it)
if(strcmp(it->second,“foo”))
打破
通过存储反向映射:

std::map<int, string> fmap;
std::map<string, int> bmap;

fmap.insert(std::make_pair(0, "foo"));
bmap.insert(std::make_pair("foo", 0));

fmap[0]; // original map lookup

bmap["foo"]; //reverse map lookup
std::map-fmap;
地图地图;
fmap.insert(标准:制作成对(0,“foo”);
bmap.insert(std::make_pair(“foo”,0));
fmap[0];//原始地图查找
bmap[“foo”]//反向地图查找

不,您不能这样做。您只需在map上迭代,将每个值与要匹配的项进行匹配,并返回相应的键,这将花费相当于O(n)的高时间复杂度。

仅通过迭代进行。不,不完全如此。让另一个映射以另一种方式运行,并保持这两个映射的同步。您可能会感兴趣,如果您想要强大的异常安全性,则需要在第二个插入失败时撤消第一个插入。这里的内存使用和局部性并不理想。从这个角度来看,我推荐boost multi index。@MaximYegorushkin你说得对。“我的回答的后半部分只提供了一个快速而肮脏的解决方案,其中有一些针对Boost过敏的编码人员的缺陷,这似乎很常见。@MaximYegorushkin,但感谢您指出这一点。我在回答中添加了一个提示。自从我上次遇到提振厌恶已经有好几年了。或者可能是我很小心地找到了一份工作,只要它是正确的和足够快的。无论如何,我发现boost多索引库是boost中最有用的库之一。只要提到,如果您有非唯一的值,您可以使用std::multimap myMapBackward。
std::map<int, string> fmap;
std::map<string, int> bmap;

fmap.insert(std::make_pair(0, "foo"));
bmap.insert(std::make_pair("foo", 0));

fmap[0]; // original map lookup

bmap["foo"]; //reverse map lookup