c++按键和值搜索容器

发布于 2024-09-07 23:39:44 字数 576 浏览 2 评论 0原文

我正在尝试构建一个序数字符串表示形式的容器,可以通过字符串和数字进行搜索。例如,我可以使用数组简单但效率低下:

std::string ordinalStrings = {"zeroth", "first", "second",..}

使用 ordinalStrings[number] 获取字符串,并使用 while(未找到)循环获取整数,但我认为其中一个 STL 容器会做得更好工作,只是不确定是哪一份。

它不需要两者都可以搜索,例如,简单地用字符串键获取地图的数字键就可以了,但似乎没有一个函数可以实现它,而且,它看起来有点混乱。

顺便说一句,是否可以有一个恒定的 STL 容器?我只需要搜索功能,不需要插入。另外,因为我认为我不能,是否可以在没有初始化函数的情况下填充容器?也就是说,标题是否可以简单地说:

std::map<std::string, int> ordinals;
ordinals["zero"] = 0;
ordinals["one"] = 1;
...

对于本质上是常量值的初始化函数似乎很愚蠢;

谢谢, 怀亚特

I'm trying to build a container of string representations of ordinal numbers, searchable both by the string and by the number. For example, I can do it trivially, but inefficiently, with an array:

std::string ordinalStrings = {"zeroth", "first", "second",..}

getting the string with ordinalStrings[number], and the integer with a while(not found) loop, but I figure that one of the STL containers would do a better job, just not sure which one.

It needn't be searchable by both, for example, simply getting the numerical key of a map with a string key would work, but there doesn't seem to be a function for it, and besides, it seems a little messy.

As an aside, is it possible to have a constant STL container? I only need the searching functionality, not the insertion. Also, since I assume I can't, is it possible to fill the container without an initializer function? That is, can a header simply say:

std::map<std::string, int> ordinals;
ordinals["zero"] = 0;
ordinals["one"] = 1;
...

It just seems silly to have an initializer function for what is essentially a constant value;

Thanks,
Wyatt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稀香 2024-09-14 23:39:44

Stephen 建议使用 Boost.MultiIndex,但这有点矫枉过正。

Boost.Bimap 已开发并提供额外的功能。事实上,它是专门为这项任务量身定制的。它也是少数几个拥有(恕我直言)良好文档的库之一:)

这是来自 此页面

#include <iostream>

#include <boost/bimap.hpp>

struct country  {};
struct place    {};

int main()
{
    using namespace boost::bimaps;

    // Soccer World cup.

    typedef bimap
    <
        tagged< std::string, country >,
        tagged< int        , place   >

    > results_bimap;

    typedef results_bimap::value_type position;

    results_bimap results;
    results.insert( position("Argentina"    ,1) );
    results.insert( position("Spain"        ,2) );
    results.insert( position("Germany"      ,3) );
    results.insert( position("France"       ,4) );

    std::cout << "Countries names ordered by their final position:"
                << std::endl;

    for( results_bimap::map_by<place>::const_iterator
            i    = results.by<place>().begin(),
            iend = results.by<place>().end() ;
            i != iend; ++i )
    {
        std::cout << i->get<place  >() << ") "
                  << i->get<country>() << std::endl;
    }

    std::cout << std::endl
              << "Countries names ordered alphabetically along with"
                 "their final position:"
              << std::endl;

    for( results_bimap::map_by<country>::const_iterator
            i    = results.by<country>().begin(),
            iend = results.by<country>().end() ;
            i != iend; ++i )
    {
        std::cout << i->get<country>() << " ends "
                  << i->get<place  >() << "º"
                  << std::endl;
    }

    return 0;
}

Stephen suggested using Boost.MultiIndex, however it's a bit an overkill.

Boost.Bimap has been developped over it, and offer extra functionalities. It is in fact tailored right for this task. It's also one of the few libraries which has (imho) a good documentation :)

Here is an example right from this page.

#include <iostream>

#include <boost/bimap.hpp>

struct country  {};
struct place    {};

int main()
{
    using namespace boost::bimaps;

    // Soccer World cup.

    typedef bimap
    <
        tagged< std::string, country >,
        tagged< int        , place   >

    > results_bimap;

    typedef results_bimap::value_type position;

    results_bimap results;
    results.insert( position("Argentina"    ,1) );
    results.insert( position("Spain"        ,2) );
    results.insert( position("Germany"      ,3) );
    results.insert( position("France"       ,4) );

    std::cout << "Countries names ordered by their final position:"
                << std::endl;

    for( results_bimap::map_by<place>::const_iterator
            i    = results.by<place>().begin(),
            iend = results.by<place>().end() ;
            i != iend; ++i )
    {
        std::cout << i->get<place  >() << ") "
                  << i->get<country>() << std::endl;
    }

    std::cout << std::endl
              << "Countries names ordered alphabetically along with"
                 "their final position:"
              << std::endl;

    for( results_bimap::map_by<country>::const_iterator
            i    = results.by<country>().begin(),
            iend = results.by<country>().end() ;
            i != iend; ++i )
    {
        std::cout << i->get<country>() << " ends "
                  << i->get<place  >() << "º"
                  << std::endl;
    }

    return 0;
}
山川志 2024-09-14 23:39:44

您可以使用 boost::multi_index 提供两种不同的查找机制 (这是一个 双向地图的示例 使用 multi_index)。另一种(也许更简单)的选择是维护两个容器:一个按序号查找,一个按字符串搜索。您可以使用两个 std::map 或一个 std::map 和一个 std::vector (用于常数时间查找序数)。

顺便说一句,是否可以有一个常量的 STL 容器?我只需要搜索功能,不需要插入。

是的,但是您必须初始化一个非常量容器。然后,您可以将其复制到 const 容器中。例如,您可以使用辅助函数: const std::map;序数= create_map();

也就是说,标题可以简单地说:...

不,您应该在适当的控制流中初始化容器。

You can provide two different lookup mechanisms using boost::multi_index (here's an example of a bidirectional map using multi_index). Another (maybe simpler) option is to maintain two containers: one to lookup by ordinal, one to search by string. You could use two std::map or a std::map and a std::vector (for constant time lookup of ordinality).

As an aside, is it possible to have a constant STL container? I only need the searching functionality, not the insertion.

Yes, but you must initialize a non-const container. You can then copy that into a const container. For example, you can use a helper function: const std::map<string, int> ordinals = create_map();

That is, can a header simply say: ...

No, you should initialize the container within a proper control flow.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文