【问题标题】:Effectively getting items from map based on specific sort根据特定排序有效地从地图中获取项目
【发布时间】:2021-08-24 02:05:52
【问题描述】:

我有一个相当简单的问题:我有一个std::map<int,T> 和另一个std::set<int>(也可以是std::vector 或类似的)。

在地图中我存储项目,在另一个容器中我存储(地图的)收藏夹。

在某些时候,我需要从地图中检索(所有)项目,但从另一个容器定义的收藏夹开始。

这是我的最小复制,我解决它非常丑陋,而且无效:

#include <iostream>
#include <string>
#include <set>
#include <map>

using namespace std;

map<int, string> myMap;
set<int> myFavorites;


int main()
{
    
    myMap.emplace(1, "but I don't like this");
    myMap.emplace(12, "So it will go below");
    myMap.emplace(31, "This one will come first, and");
    myMap.emplace(44, "under my favorites");
    myMap.emplace(52, "then this will follow");
    
    myFavorites.insert(52);
    myFavorites.insert(31);
    
    cout << "My map:" << endl;
    for(auto p : myMap) {
        cout << "#" << p.first << "=" << p.second << endl;
    }
    
    cout << endl << "My favorites:" << endl;
    for(auto p : myFavorites) {
        cout << "#" << p << endl;
    }
    
    cout << endl << "All items starting with my favorites:" << endl;
    for(auto p : myFavorites) {
        auto item = myMap.find(p);
        if (item != myMap.end()) cout << "#" << item->first << "=" << item->second << endl;
    }
    for(auto p : myMap) {
        if (myFavorites.find(p.first) != myFavorites.end()) continue;
        cout << "#" << p.first << "=" << p.second << endl;
    }
}

真正困扰我的是最后一个循环,每次迭代都会在set 上调用find

需要的输出是:

All items starting with my favorites:
#31=This one will come first, and
#52=then this will follow
#1=but I don't like this
#12=So it will go below
#44=under my favorites

这里是 Coliru 中的上述源代码,以使其更容易:https://coliru.stacked-crooked.com/a/731fa76d90bfab00

map 和 set 都可以更改,但替换需要实现与原始接口相同的接口。

我正在寻找一种比我原来的“蛮力”解决方案更有效的方法。

请注意:地图不得“重新排序”!我只需要使用自定义排序查询(检索)它的项目!

注2:我知道地图可以有一个比较运算符。但我通常需要原始顺序,有时我需要自定义排序!

注意 3:Boost 不可用,编译器支持 C++14。

【问题讨论】:

  • 也许您可以考虑使用额外的存储空间,特别是一个名为“favorite”的vector &lt;pair&lt;int, T&gt;&gt; 和一个名为“other”的。然后,您可以通过简单地遍历所有地图元素来实现这种输出 - 对于每个元素,检查它是否在“收藏夹”集中。如果是,则将其添加到“收藏夹”,否则将其添加到“其他”。最后,要获得输出,只需先在“收藏夹”中打印所有内容,然后在“其他”中打印所有内容。这样做的问题是存储需求可能等于地图的大小,如果地图很大,这可能会很糟糕。

标签: c++ sorting dictionary


【解决方案1】:

std::mapstd::set 都使用相同的严格弱排序来对其内容进行排序。

您可以利用这一点。您知道,如果您遍历地图,您将按照与集合中相同的顺序获取键,因此只需要一点聪明的逻辑,例如:

auto map_iter=myMap.begin();

for(auto p : myFavorites) {
    while (map_iter != myMap.end())
    {
         if (map_iter->first == p)
            cout << "#" << map_iter->first << "=" << map_iter->second << endl;
         if (map_iter->first > p)
              break;
         ++map_iter;
     }
}

在某些边缘情况下使用find() 可能仍然有意义,特别是当myFavorites 明显小于myMap 时,在这种情况下,对find() 的几次调用可能比迭代更快(大部分) 整个地图。

【讨论】:

  • 但我需要地图中的所有项,而不仅仅是收藏夹。这似乎只是从地图中提取收藏夹。
  • 好吧,内部循环几乎在整个地图上进行迭代,所以只需对其中的其他值做任何您需要做的事情,并在此之后添加最终的while 循环迭代,覆盖地图中的剩余值。你明白我的例子的逻辑是如何工作的吗?如果没有,请随时要求澄清您不清楚的地方。如果你这样做了,那么为了实现这一点,对该算法的微小修改应该是相当简单的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 2017-02-25
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 2022-09-30
  • 1970-01-01
相关资源
最近更新 更多