C++ 反向映射地图<;字符串,int>;到向量<;向量<;字符串>&燃气轮机;

C++ 反向映射地图<;字符串,int>;到向量<;向量<;字符串>&燃气轮机;,c++,stl,C++,Stl,在我的基础上,我有一个单词映射&它们的计数存储在映射中。我想把它颠倒过来,这样所有计数相同的单词都被分组在一起。我的解决方案是使用向量。第一个向量的索引是计数,第二个向量是单词的集合 在阅读了前一个问题的答案后,这里是我一直在努力的: vector<vector<string> > sorted_words; for (map<string, int>::const_iterator it = counters.begin(); it

在我的基础上,我有一个单词映射&它们的计数存储在
映射中。我想把它颠倒过来,这样所有计数相同的单词都被分组在一起。我的解决方案是使用
向量
。第一个向量的索引是计数,第二个向量是单词的集合

在阅读了前一个问题的答案后,这里是我一直在努力的:

  vector<vector<string> > sorted_words;
    for (map<string, int>::const_iterator it = counters.begin();
       it != counters.end(); ++it) {
    cout << "word:" << it->first
         << " count:" << it-> second
         << " vector size: " << sorted_words.size()
         << endl;

    if (sorted_words.size() - 1 > it->second && 
        sorted_words[ it->second ].size() > 0) {
      cout << "Adding " << it->first << endl;
      sorted_words[ it->second ].push_back(it->first);
    } else {
      cout << "Creating " << it->first << endl;
      vector<string> v;
      v.push_back(it->first);
      sorted_words.resize( it->second + 1 );
      sorted_words[it->second] = v;
    }
  }
向量排序的单词;
对于(map::const_迭代器it=counters.begin();
it!=counters.end();++it){
cout second]=v;
}
}
这将导致在循环的第一个过程中if语句处出现segfault

我想做的是看看外部向量的大小是否使我的当前值在边界内&如果是,如果我已经创建了一个嵌套向量。(我需要这样做,因为映射可以按任何顺序返回。例如,第一个元素可以是。)


如果我是以一种基本上非C++的方式来做这件事,请随意指出。

快速猜测:
排序的单词。size()
是某种无符号类型(即
size\t
),所以
排序的单词。size()-1
即使在应该是-1时也是无符号的(最初)因此,您总是通过第一个条件,如果条件的第二个条件求值并崩溃。

对于空间,您最好使用
std::map
。以下相当简单的代码(可以通过降低所有单词的大小写并去掉标点符号来改进)演示了:

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
using namespace std;

int main(int argc, char *argv[])
{
    if (argc < 2)
        return EXIT_FAILURE;

    // map of strings to counts.
    std::map<string, int> strs;
    ifstream inf(argv[1]);
    string str;
    while (inf >> str)
        ++strs[str];

    // map of counts to strings, smallest to largest.
    std::map<int, std::vector<string>> vals;
    for (auto it : strs)
        vals[ it.second ].push_back(it.first);

    // report counts for each
    for (auto it : vals)
    {
        cout << "Count: " << it.first << ": ";
        std::copy(it.second.begin(), it.second.end(),
                  ostream_iterator<string>(cout, " "));
        cout << endl;
    }
}
样本输出

Count:1:反正就算是在进了嫉妒的最后一刻,也没有人寻觅叹息,于是他们就变成了不情愿再行动的年龄。全部,武器。歌谣胡子胡子是肚子大泡泡大炮的卡彭稚气的匍匐切割,结束入口;多事的一切。我的眉毛。眼睛,脸,首先是公平的,正式的炉,良好的历史,荣誉,软管,婴儿,实例;正义、瘦削、情人、男人许多男人仅仅是情妇现代的早晨的嘴。鼻子护士的誓言遗忘,一个潘塔隆,伙计,部分。零件、管乐器演奏者:眼袋呕吐吵架,快声名圆圆的书包得救,锯场景学童,学校。第二个严重的小腿;第六只拖鞋的蜗牛那个样的士兵,声音。眼镜台上,突如其来的味道,牙齿,这一次也朝着高音,声音,以及呜呜的口哨声广博睿智可悲的世界女性的青春
伯爵:2:满脑子都是他对他们奇怪的把戏
计数:3:像sans那样
计数:4:1
计数:6:英寸
伯爵:7:他的
计数:8:和
计数:11:和
有趣的是,独白中有那么多独特的字串。就像他那样计划的。然而,当考虑到大写和标点符号删除时,数字明显不同。谢天谢地,这样做也很简单,只更改了第一个while循环:

while (inf >> str)
{
    string alpha;
    for_each(str.begin(), str.end(),
            [](char& c){c=tolower(static_cast<unsigned char>(c));});
    copy_if(str.begin(), str.end(), back_inserter(alpha),
            [](const char& c){return isalpha(static_cast<unsigned char>(c));});
    ++strs[alpha];
}
不过,还是很令人印象深刻,比利


由于第一次地图排序的性质,您可以获得按字母顺序排列的单词列表。寻找额外功能。

如果要反转
贴图
,请使用
贴图
。如果您不关心该点的实际计数是多少,您可以通过从中间映射移动来高效地构建
向量。例如:

vector<vector<string>> invert(const map<string, int>& input) {

  map<int, vector<string>> inverse;
  for (const auto& pair : input)
    inverse[pair.second].push_back(pair.first);

  vector<vector<string>> result;
  for (auto& pair : inverse)
    result.push_back(move(pair.second));

  return result;

}
矢量反转(常量映射和输入){
映射逆;
用于(常数自动和配对:输入)
反向[pair.second]。向后推(pair.first);
矢量结果;
用于(自动配对:反向(&P)
结果:推回(移动(第二对));
返回结果;
}

您可以利用已有的映射(
映射
),只需创建一个
向量
,即可收集具有相同计数的所有单词的索引,而无需使用
向量
。这将为您节省大量空间。另外,当你修改以前的
地图时,你所需要做的就是更新
向量中的索引,这将比其他两种方法更快。

地图是这样做的一种方法。所以从根本上说,我尝试使用向量是走错了路?这取决于:大多数索引是否已满(即有大小为1、2、3、…)的单词)如果不是map是更好的选择,那么vector是好的。vector of vectors的问题是,你的外部向量似乎很稀疏——如果你有一对出现数千次的单词,但没有出现100到1000次之间的单词呢?你的内部将有900个无用的向量!你可以使用一个,尽管我更喜欢
std::map
就我个人而言。