LoginSignup
8
8

More than 5 years have passed since last update.

怠惰にコンテナを処理する

Last updated at Posted at 2014-07-12

 C++ Streams というライブラリがあります。これは、平たく言うとコンテナに対する処理を提供するもので、標準の汎用アルゴリズム、Boost.Range、PStade.Oven などの競合に当たります。

 ワードカウントやります。始めは、標準のアルゴリズムを使います。

#include <algorithm>
#include <iostream>
#include <regex>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

int main() {
  auto sentence = std::string("You play with the cards you're dealt... whatever that means.");

  sentence = std::regex_replace(sentence, std::regex("[^a-zA-Z]"), "");
  std::transform(sentence.begin(), sentence.end(), sentence.begin(), ::toupper);

  const auto counts =
    std::accumulate(sentence.begin(), sentence.end(), std::unordered_map<char, int>(), [](auto counts, auto word) {
      counts.insert(std::make_pair(word, ++counts[word]));
      return counts;
    });

  auto result = std::vector<std::pair<char, int>>(counts.begin(), counts.end());
  std::sort(result.begin(), result.end(), [](auto a, auto b) {
    return b.second < a.second;
  });
  std::for_each(result.begin(), result.end(), [](auto pair) {
    std::cout << pair.first << ": " << pair.second << std::endl;
  });
}

次に、脱アルゴリズム宣言します。

#include <iostream>
#include <regex>
#include <string>
#include <unordered_map>
#include <utility>

#include "Stream.h"

int main() {
  using streams = stream::MakeStream;

  const auto sentence = std::string("You play with the cards you're dealt... whatever that means.");

  const auto counts =
    streams::from(std::regex_replace(sentence, std::regex("[^a-zA-Z]"), ""))
    .map(::toupper)
    .reduce(std::unordered_map<char, int>(), [](auto counts, auto word) {
      counts.insert(std::make_pair(word, ++counts[word]));
      return counts;
    });

  streams::from(counts).sort([](auto a, auto b) {
    return b.second < a.second;
  })
  .for_each([](auto pair) {
    std::cout << pair.first << ": " << pair.second << std::endl;
  });
}

 唐突ですけど、C++ Streams と Boost.Asio と標準の正規表現を使ってみたかったので、ウェブスクレイピングやります。

#include <iostream>
#include <regex>
#include <string>
#include <vector>
#include <boost/asio.hpp>
#include <boost/format.hpp>

#include "Stream.h"

int main() {
  using streams = stream::MakeStream;

  const auto source =
    streams::range(0, 3).reduce(std::string(), [](std::string source, int offset) {
      boost::asio::ip::tcp::iostream stream("cpplover.blogspot.jp", "http");
      stream << boost::format("GET /search?q=pdf&start=%d HTTP/1.0\r\n") % (offset * 20)
             << "Host: cpplover.blogspot.jp\r\n\r\n"
             << std::flush;

      for (std::string line; std::getline(stream, line); ) {
        source += line;
      }

      return source;
    });

  const auto re = std::regex("\\.pdf\">\\[(.+?)\\]");
  const auto begin = std::sregex_iterator(source.begin(), source.end(), re);
  const auto end = std::sregex_iterator();
  streams::from(begin, end).for_each([](auto s) {
    std::cout << s[1].str() << std::endl;
  });
}
$ g++ main.cpp -std=c++14 -lboost_system -I ./Streams/source/

楽しい! ✌(’ω’✌ )三✌(’ω’)✌三( ✌’ω’)✌

jscheiny/Streams - GitHub

Boost.Asio - boost C++ Libraries

<regex> - C++ Reference

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8