【问题标题】:C++, Order map content based on second iterC ++,基于第二个迭代器排序地图内容
【发布时间】:2012-08-04 13:42:19
【问题描述】:

我有如下地图

string word;
int occurance;
std::map< std::string, std::map<string, int> > map;
map[word]["count"] = occurance;

使用迭代器映射输出。

for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
        for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter) {
            std::cout << outer_iter->first << '\t'  << inner_iter->second << std::endl;
        }
    }

我想通过排序 inner_iter->second 值来显示地图。

我该怎么做?

【问题讨论】:

  • 如果你写的是std::cout,那么你也应该写std::map
  • 糟糕,我使用了 using namespace std;
  • 您可能对 Boost.Bimap (boost.org/doc/libs/release/libs/bimap/doc/html/index.html) 感兴趣。
  • 是的,只需执行myBimap.right 即可获得反向映射,其中元素按出现次数排序。请参阅我的答案以获取示例链接。

标签: c++ string iterator int


【解决方案1】:

最简单的使用方法(除非配置文件另有说明)是在需要打印时简单地制作一张由内向外的地图:

std::multimap<int, std::string> inverse_map;

for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter)
{
    for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter)
    {
        inverse_map.insert(std::make_pair(inner_iter->second, outer_iter->first));
    }
}

然后你只需循环遍历倒置的地图并正常打印。

编辑:我认为您可以通过使用 set 对来获得所需的双重排序:

std::set<std::pair<int, std::string> > inverse_map;

for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter)
{
    for(auto inner_iter=outer_iter->second.begin(); inner_iter!=outer_iter->second.end(); ++inner_iter)
    {
        inverse_map.insert(std::make_pair(inner_iter->second, outer_iter->first));
    }
}

【讨论】:

  • 非常感谢它的工作,但我有一个我忘记提及的问题,我的错。我需要根据最高发生率显示到最低发生率。我用你的技术得到了它,但我需要得到的第二件事是如果出现相同,那么它应该显示单词字符串的字母顺序
  • @user1579911:您可以在multimap 上使用reverse_iterator。从rbegin() 开始并递增直到rend()
  • 非常感谢您的帮助。我只需要删除“计数”,这对我来说太愚蠢了。无论如何,谢谢我学会了如何反转地图。
  • +1 用于实现关联不是双射的(因此是多图)。
  • 此解决方案本质上是按发生顺序进行树排序 (en.wikipedia.org/wiki/Tree_sort)。
【解决方案2】:

您可以插入vector 并相应地对内容进行排序。

编辑:修改为从高到低排序。

typedef std::pair<std::string, int> hist_item;
std::vector<hist_item> hist;
hist.reserve(map.size());

for(auto outer_iter=map.begin(); outer_iter!=map.end(); ++outer_iter) {
    for(auto inner_iter=outer_iter->second.begin();
        inner_iter!=outer_iter->second.end(); ++inner_iter) {
        hist.push_back(std::make_pair(outer_iter->first, inner_iter->second));
    }
}
std::sort(hist.begin(), hist.end(),
          [](const hist_item &a,const hist_item &b){return a.second>b.second;});
for (auto i = hist.begin(); i!= hist.end(); ++i) {
    std::cout << i->first << '\t' << i->second << std::endl;
}

这模仿了您的原始输出。我不确定内部地图的用途。如果您在其中跟踪 "count" 以外的属性,则您的原始输出和此例程将失去该关联,并且您只会获得与外部单词关联的多个数字。

【讨论】:

  • 你说得对,我不需要“计数”啊,我只想把头撞到墙上。非常感谢它已修复。
【解决方案3】:

如果您愿意使用 Boost,可以使用 Boost::Bimap,它可以让您将单词与计数相关联,并将计数与单词(同时)相关联。这个example 展示了如何计算文本的字数并显示直方图。

如果您只需要偶尔显示排序后的字数,使用常规的std::map 构建字数图可能会更快。然后,您可以使用其他答案中显示的技术根据需要生成排序的字数。您可能必须运行基准测试才能知道哪个更快。


为了完整起见,我将添加另一个使用heapsort 的解决方案,方法是通过std::priority_queue 推送地图对以获得按出现排序的字数:

#include <iostream>
#include <map>
#include <queue>

typedef std::map<std::string, int> MyMap;

struct OrderByOccurence
{
    bool operator()(MyMap::const_reference lhs, MyMap::const_reference rhs)
    {
        // This will make the priority queue sort from highest word count
        // to lowest.
        return lhs.second < rhs.second;

        // This will make the priority queue sort from lowest word count
        // to highest.
        // return rhs.second < lhs.second;

        // Here, you can also check that if both counts are the same,
        // the elements should be ordered alphabetically by word.
    }
};

int main()
{
    MyMap m = {{"a", 1}, {"b", 2}, {"c", 3}};

    std::priority_queue<std::pair<std::string, int>,
                        std::vector< std::pair<std::string, int> >,
                        OrderByOccurence> q;
    for (auto it=m.begin(); it!=m.end(); ++it)
        q.push(*it);

    while (!q.empty())
    {
        std::cout << q.top().first << " " << q.top().second << "\n";
        q.pop();
    }
}

【讨论】:

    猜你喜欢
    • 2014-07-26
    • 2023-03-09
    • 2010-12-02
    • 2019-05-24
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    相关资源
    最近更新 更多