使用带有std :: set的自定义比较器

时间:2014-09-26 08:53:13

标签: c++

我正在尝试创建一个按文件长度排列的文件列表。为此,我试图使用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

知道这里发生了什么?

2 个答案:

答案 0 :(得分:3)

使用比较器,等长字是等效的,并且您不能在一组中有重复的等效条目。

要保持多个单词,您应该修改比较器,以便在长度相同的情况下执行词典比较。

答案 1 :(得分:0)

您的比较器仅按长度进行比较,这意味着同等大小但不同的字符串被std::set视为等效。 (std::set如果a < bb < a都不为真,则<同等对待它们,std::tuple是您的自定义比较函数。)

这意味着您的比较器也应该考虑字符串内容以避免这种情况。此处的关键字是词典比较,这意味着您可以考虑多个比较条件。第一个标准是你的字符串长度,第二个标准是字符串本身。编写字典比较的一种简单方法是使用operator<,它提供了一个比较运算符,通过重载operator>来对组件进行字典比较。

让你的&#34;反向&#34;您使用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 } }; 进行比较:

{{1}}