繁体   English   中英

转换 std::string::iterator 以适应 boost::multi_index_container 'insert' function

[英]Convert std::string::iterator to fit into boost::multi_index_container 'insert' function

有这个例子,特别是它的这一部分:

text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
  unsigned int   total_occurrences=0;
  for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end();
      it!=it_end;++it){
    /* Insert the word into the container. If duplicate, wit will point to
     * the preexistent entry.
     */

    ++total_occurrences;
    word_counter::iterator wit=wc.insert(*it).first;

我想做基本相同的事情,但是使用 std::string::iterator 因为我需要将字符串中的单独字符插入到容器中:

  for (std::string::iterator it=text.begin(),it_end=text.end();
       it!=it_end;++it)
  {
      word_counter::iterator wit=wc.insert(*it).first;
  }

我收到以下错误:

no known conversion for argument 1 from ‘char’ to ‘const value_type&’ {aka ‘const word_counter_entry&’}
  299 |   std::pair<iterator,bool> insert(const value_type& x)
      |                                   ~~~~~~~~~~~~~~~~~~^

字符不是字符串。 如果你真的想进行这种转换,你可以:

word_counter   wc;
for (std::string::iterator it=text.begin(),it_end=text.end();
       it!=it_end;++it)
{
    char ch = *it;
    std::string str(1, ch);
    word_counter::iterator wit=wc.insert(str).first;
}

请注意,使用 C++11 您可以大大改善这一点:

word_counter wc;
for (char ch : text) {
    auto [wit, _] = wc.emplace(std::string{1, ch});
}

更简单的频率直方图

但是,也许您真的想要一个字母计数器,所以为什么不只是:编译器资源管理器

#include <array>
#include <fmt/ranges.h>

using namespace std::string_view_literals;

int main() {
    std::array<size_t, 256> histogram{};
    for (char ch : "as the world turns!"sv) {
        ++histogram[ch];
    }

    fmt::print("Result: {}\n", histogram);
}

使用 Map

这仅打印看到的字符: Compiler Explorer

#include <map>
#include <fmt/ranges.h>

using namespace std::string_view_literals;

int main() {
    std::map<char, size_t> histogram;
    for (char ch : "as the world turns!"sv) {
        ++histogram[ch];
    }

    fmt::print("Result: {}\n", histogram);
}

印刷

Result: {(' ', 3), ('!', 1), ('a', 1), ('d', 1), ('e', 1), ('h', 1), ('l', 1), ('n', 1), ('o', 1), ('r', 2), ('s', 2), ('t', 2), ('u', 1), ('w', 1)}

高级 C++20:排序,Top-5

如果你有范围,你可以添加排序和 Top-N: Compiler Explorer

#include <map>
#include <fmt/ranges.h>
#include <ranges>

using namespace std::string_view_literals;
using Histo = std::map<char, size_t>;
using Entry = Histo::value_type;

namespace r = std::ranges;
namespace v = r::views;

int main() {
    Histo histo;
    for (char ch : "as the world turns!"sv) {
        ++histo[ch];
    }

    auto flip = histo | v::transform([](Entry& e) { return std::tuple(e.second, e.first); });
    std::vector ranking(flip.begin(), flip.end());
    std::ranges::sort(ranking, std::greater_equal<>{});

    fmt::print("Result: {}\n", ranking | v::take(5));
}

印刷

Result: {(3, ' '), (2, 't'), (2, 's'), (2, 'r'), (1, 'w')}

更高效

无需动态分配 map:编译器资源管理器

#include <map>
#include <fmt/ranges.h>
#include <ranges>

using namespace std;
using namespace string_view_literals;

namespace r = ranges;
namespace v = r::views;

int main() {
    array<size_t, 256> histo{};
    for (char ch : "as the world turns!"sv) {
        ++histo[ch];
    }

    auto flip = histo
        | v::transform([ch='\0'](size_t freq) mutable { return tuple(freq, ch++); });

    vector ranking(flip.begin(), flip.end());
    ranges::sort(ranking, greater_equal<>{});

    fmt::print("Result: {}\n", ranking | v::take(5));
}

印刷

Result: {(3, ' '), (2, 't'), (2, 's'), (2, 'r'), (1, 'w')}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM