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
就我个人而言。