【问题标题】:efficient way to get key from std::map value从 std::map 值获取密钥的有效方法
【发布时间】:2018-07-30 04:50:45
【问题描述】:

我有一张地图如下:

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

当输入为值时如何获取key

前:

输入:1

输出:一个

注意:在我的情况下,值是唯一的

【问题讨论】:

  • std::map 的设计不是为了有效地做到这一点,你可能需要别的东西。

标签: c++ performance stdmap


【解决方案1】:

一对一的映射实际上很容易,最快的方法是维护两个映射,每个方向一个。如果它不是一对一的,它会变得更加复杂,因为您需要提供一种方法来获取值或键的集合,而不是单个的。幸运的是,您只有一对一的要求。

其中一个映射是您现在拥有的映射,另一个会将值映射到给定键,所以两者都是:

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

这些将被维护在某种bidimap 类中。

每当您插入或删除bidimap 时,您都必须对两个 内部映射执行等效操作。

例如,这里有一些伪代码。它维护两个映射,并确保它们在您进行的任何更改键和值的操作时保持同步:

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]

显然,您可以添加许多其他内容,但这应该构成基础。无论如何,在将其转换为 C++ 类之前,您可能已经完成了足够的工作:-)


如果您想要推出自己的解决方案,那么 Boost 有一个非常好的解决方案,您可以按原样使用它。 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;
}

它在数字的文本形式和整数值之间创建双向映射,然后进行一些查找(在两个方向上)以表明它有效:

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

【讨论】:

  • 嗨,我需要你的帮助。我有超过 300 个需要映射的键值对我正在初始化级别进行此映射。添加 300 个键值是好的还是我应该维护一个文件,其中所有键和值的列表都可用,我将使用 add 方法在地图中插入。你能建议最好的方法吗?
  • @Ysurf:最好是完全用硬编码值的代码完成,还是在某个时间从文件中读取,主要取决于数据更改的频率以及谁来更改它。如果您的代码的用户永远不会更改它,并且您不介意在必须更改时发布新版本,那么在代码中就可以了。如果您想在没有新版本的情况下更改它,或者如果您希望用户能够更改它,那么在启动时读取文本文件会更好。
  • 知道了,谢谢 ;-)
  • @Ysurf:我还为您提供了一个使用 Boost 的 bimap 的 C++ 解决方案,这是一个双向映射,可能比您(或我,就此而言)可以做的任何事情都要好我们自己做:-)
【解决方案2】:

我注意到这有“stdmap”标签,所以这可能不合适。然而Boostboost::bimap&lt;&gt; 可以让你做你想做的事:它允许通过键或值查找。

【讨论】:

    【解决方案3】:

    当输入为值时如何获取key

    1. 首先,不能保证值是唯一的。我意识到你说它是独一无二的。不过,从概念上讲,在查看问题时要牢记这一点。

    2. 其次,std::map 不按值排序。因此,查找值的最有效算法平均为O(N)

    【讨论】:

    • 在我的情况下,值是唯一的。你能帮我提供示例代码吗?
    • @Ysurf,遍历地图项并比较值。我希望你完全有能力做到这一点。如果您不知道该怎么做,是时候投资a good book 并学好这门语言了。
    【解决方案4】:

    尝试增强 Bimap。您尝试做的所有事情都可以简单地由它完成。

    1 --> 一个 2 --> 两个 ... 一个 --> 1 两个 --> 2 ...

    这是一个链接,其中存在一个工作示例。 here

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      相关资源
      最近更新 更多