简体   繁体   English

从std :: map值获取密钥的有效方法

[英]efficient way to get key from std::map value

I have a map as below : 我有一张地图如下:

std::map< std::string ,int> mapobj;
mapobj["one"] = 1;
mapobj["two"] = 2;
mapobj["three"] =3 ;

how to get key when input is value 输入值时如何获取键

EX : EX:

input : 1 输入:1

output : one 输出:一

Note : In my case value is unique 注意:在我的情况下,值是唯一的

A one-to-one mapping is actually quite easy, the fastest way to do it is to probably maintain two maps, one for each direction. 一对一映射实际上非常简单,最快的方法是维护两个映射,每个映射一个。 It becomes more complicated if it's not one-to-one since you'll need to provide a way to get a collection of values or key, rather than a single one. 如果它不是一对一的话会变得更加复杂,因为你需要提供一种方法来获取值或键的集合 ,而不是单个的。 Happily, you only have the one-to-one requirement. 令人高兴的是,你只有一对一的要求。

One of the maps is the one you have now, the other will map the values to a given key, soboth would be: 其中一个地图是你现在拥有的地图,另一个地图将值映射到给定的密钥,soboth将是:

std::map<std::string, int> forwardmapobj;
std::map<int, std::string> reversemapobj;

and these would be maintained within a bidimap class of some sort. 这些将保持在某种bidimap类中。

Whenever you insert to, or delete from, your bidimap , you have to perform the equivalent operation on both internal maps. 无论何时插入或删除bidimap ,都必须在两个内部地图上执行等效操作。

For example, here's some pseudo-code. 例如,这是一些伪代码。 It maintains the two maps and ensures that they'e kept in sync for whatever operations you have that change the keys and values: 它维护着两个映射,并确保它们与您更改键和值的任何操作保持同步:

class biDiMap:
    map<string, int> forwardMap
    map<int, string> reverseMap

    void add(string key, int val):
        if exists forwardMap[key]: throw exception 'duplicate key'
        if exists reverseMap[val]: throw exception 'duplicate value'
        forwardMapObj[key] = val
        reverseMapObj[val] = key

    void delKey(string key):
        if not exists forwardMap[key]: throw exception 'no such key'
        delete reverseMap[forwardMap[key]]
        delete forwardMap[key]

    void delVal(int val):
        if not exists reverseMap[val]: throw exception 'no such value'
        delete forwardMap[reverseMap[val]]
        delete reverseMap[val]

    int getValFor(string key): return forwardMap[key]

    string getKeyFor(int val): return reverseMap[val]

Obviously, there's plenty of other stuff you could add but that should form the basis. 显然,你可以添加许多其他东西,但这应该构成基础。 In any case, you've probably got enough work ahead of you turning that into a C++ class :-) 无论如何,在你把它变成C ++类之前,你可能已经有了足够的工作:-)


If you don't want to roll your own solution, then Boost has a very good one that you can pretty well use as is. 如果你希望推出自己的解决方案,然后升压有一个非常好的一个,你可以作为是很好用。 Boost.Bimap provides a fully-templated bi-directional map that you should be able to use with minimal code, such as the following complete program: Boost.Bimap提供了一个完全模板化的双向映射,您应该能够使用最少的代码,例如以下完整的程序:

#include <iostream>
#include <string>
#include <boost/bimap.hpp>

using std::string;
using std::cout;
using std::exception;
using boost::bimap;

int main()
{
    typedef bimap<string, int> SiMap;
    typedef SiMap::value_type SiEntry;

    SiMap bidi;
    bidi.insert(SiEntry("ninety-nine", 99));
    int i = 0;
    for (string str: {"one", "two" , "three", "four", "five", "six"}) {
        bidi.insert(SiEntry(str, ++i));
    }

    cout << "The number of entries is " << bidi.size() << "\n\n";

    for (auto i = 1; i <= 7; i += 3) {
        try {
            cout << "Text for number " << i << " is " << bidi.right.at(i) << "\n";
        } catch (exception &e) {
            cout << "Got exception looking up number " << i << ": " << e.what() << "\n";
        }
    }
    cout << "\n";

    for (auto str: {"five", "ninety-nine", "zero"}) {
        try {
            cout << "Number for text '" << str << "' is " << bidi.left.at(str) << "\n";
        } catch (exception &e) {
            cout << "Got exception looking up text '" << str << "': " << e.what() << "\n";
        }
    }
    cout << "\n";

    return 0;
}

It creates a bi-directional mapping between the textual form of a number and the integral value, then does a few lookups (in both directions) to show that it works: 它在数字的文本形式和积分值之间创建双向映射,然后进行一些查找(在两个方向上)以显示它的工作原理:

The number of entries is 7

Text for number 1 is one
Text for number 4 is four
Got exception looking up number 7: bimap<>: invalid key

Number for text 'five' is 5
Number for text 'ninety-nine' is 99
Got exception looking up text 'zero': bimap<>: invalid key

I do notice that this has the "stdmap" tag, so this may not be appropriate. 我注意到它有“stdmap”标签,所以这可能不合适。 However Boost has boost::bimap<> which will allow you to do what you want: it allows lookup by either key or value. 但是Boostboost::bimap<>这将允许你做你想要的:它允许按键或值查找。

how to get key when input is value 输入值时如何获取键

  1. First, there is no guarantee that value is unique. 首先,不能保证价值是唯一的。 I realize that you are saying it is unique. 我意识到你说它是独一无二的。 Still, conceptually speaking, this is something to keep in mind when looking at the problem. 不过,从概念上讲,在查看问题时要记住这一点。

  2. Second, std::map is not sorted by value. 其次, std::map没有按值排序。 Hence, the most efficient algorithm to look for a value will be O(N) on an average. 因此,寻找值的最有效算法平均为O(N)

Try boost Bimap. 尝试提升Bimap。 all the things you are trying to do can simply be done by it. 你要做的所有事情都可以简单地完成。

1 --> one 2 --> two ... one --> 1 two --> 2 ... 1 - > 1 2 - > 2 ... 1 - > 1 2 - > 2 ...

here is a link where a working example is present. 这是一个存在工作示例的链接。 here 这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM