我正在尝试创建一个从文件中读取的单词列表,该列表按单词的长度排列。为此,我尝试使用带有自定义比较器的std::set。
class Longer {
public:
bool operator() (const string& a, const string& b)
{ return a.size() > b.size();}
};
set<string, Longer> make_dictionary (const string& ifile){
// produces a map of words in 'ifile' sorted by their length
ifstream ifs {ifile};
if (!ifs) throw runtime_error ("couldn't open file for reading");
string word;
set<string, Longer> words;
while (ifs >> word){
strip(word);
tolower(word);
words.insert(word);
}
remove_plurals(words);
if (ifs.eof()){
return words;
}
else
throw runtime_error ("input failed");
}从这里,我期望得到一个文件中所有单词的列表,这些单词按照它们的长度排列。相反,我得到了一个非常短的列表,每个长度只有一个单词出现在输入中:
polynomially-decidable
complexity-theoretic
linearly-decidable
lexicographically
alternating-time
finite-variable
newenvironment
documentclass
binoppenalty
investigate
usepackage
corollary
latexsym
article
remark
logic
12pt
box
on
a知道这是怎么回事吗?
发布于 2014-09-26 17:01:03
使用你的比较器,等长的单词是等价的,并且你不能在一个集合中有重复的等价条目。
要维护多个单词,您应该修改比较器,以便在长度相同的情况下也执行字典比较。
发布于 2014-09-26 17:25:57
您的比较器仅按长度进行比较,这意味着相同大小但不同的字符串被std::set视为等效。(如果a < b和b < a都不为真,则std::set对它们一视同仁,<是您的自定义比较器函数。)
这意味着您的比较器也应该考虑字符串内容,以避免这种情况。这里的关键字是字典序比较,这意味着您考虑到了多个比较标准。第一个条件是字符串长度,第二个条件是字符串本身。编写字典序比较的一种简单方法是使用std::tuple,它提供了一个比较运算符,通过重载operator<对组件执行字典序比较。
要使您用operator>编写的“反向”长度排序与通常使用的operator<兼容,只需采用字符串的负大小,即首先将a.size() > b.size()重写为-a.size() < -b.size(),然后将其与字符串本身组合成元组,最后将这些元组与<进行比较
class Longer {
public:
bool operator() (const string& a, const string& b)
{
return std::make_tuple(-a.size(), a )
< std::make_tuple(-b.size(), b );
// ^^^^^^^^^ ^^^
// first second
// criterion criterion
}
};https://stackoverflow.com/questions/26055666
复制相似问题