【问题标题】:Count the occurrences and print top K using C/STL使用 C/STL 计算出现次数并打印前 K
【发布时间】:2012-10-05 00:29:16
【问题描述】:

我有一个大文本文件,每行都有标记。我想计算每个令牌的出现次数并对其进行排序。我如何在 C++ 中有效地做到这一点,最好使用内置函数和最短的编码(当然也是最有效的)?我知道如何在 python 中执行此操作,但不确定如何在 STL 中使用 unordered_map 执行此操作。

【问题讨论】:

  • @ildjarn 正如我所提到的,我能够使用 unordered_map 计算标记的出现次数。现在我想高效优雅地找到top K(没有自己实现排序算法)。
  • 向我们展示您尝试过的代码

标签: c++ stl unordered-map


【解决方案1】:

我会采用 unordered_map 方法。对于选择最频繁的k个token,假设k小于token的总数,你应该看看std::partial_sort

顺便说一句,++frequency_map[token](例如,频率映射是std::unordered_map<std::string, long>)在 C++ 中是完全可以接受的,尽管我认为 Python 中的等价物会在新出现的标记上爆炸。

好的,给你:

void most_frequent_k_tokens(istream& in, ostream& out, long k = 1) {
  using mapT = std::unordered_map<string, long>;
  using pairT = typename mapT::value_type;
  mapT freq;
  for (std::string token; in >> token; ) ++freq[token];
  std::vector<pairT*> tmp;
  for (auto& p : freq) tmp.push_back(&p);
  auto lim = tmp.begin() + std::min<long>(k, tmp.size());
  std::partial_sort(tmp.begin(), lim, tmp.end(),
      [](pairT* a, pairT* b)->bool {
        return a->second > b->second
               || (a->second == b->second && a->first < b->first);
        });
  for (auto it = tmp.begin(); it != lim; ++it)
    out << (*it)->second << ' ' << (*it)->first << std::endl;
}

【讨论】:

    【解决方案2】:

    假设您知道如何在 C++ 中从文件中读取行,这应该是朝着正确的方向推进

    std::string token = "token read from file";
    std::unordered_map<std::string,int> map_of_tokens;
    map_of_tokens[token] = map_of_tokens[token] + 1;
    

    然后您可以将它们打印出来(用于测试):

    for ( auto i = map_of_tokens.begin(); i != map_of_tokens.end(); ++i ) {
        std::cout << i->first << " : " << i->second << "\n";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-15
      • 2018-06-25
      • 2021-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-10
      相关资源
      最近更新 更多