昨日Rでおわたになっていたので、C++でリベンジマッチをするべく準備を進める。
#include <fstream> #include <string> #include <vector> #include <map> #include <iostream> #include <mecab.h> using namespace std; vector<string> split( string s, string c ){ vector<string> ret; for( int i=0, n; i <= s.length(); i=n+1 ){ n = s.find_first_of( c, i ); if( n == string::npos ) n = s.length(); string tmp = s.substr( i, n-i ); ret.push_back(tmp); } return ret; } typedef map<string, int>::const_iterator map_freq_it; //下のみたいに毎回型を書いているのが面倒なときに別名を付けることができるのがtypedef typedef std::vector<map_freq_it>::const_iterator vec_stu_citer_t; bool compare( const map_freq_it& a, const map_freq_it& b ){ // ファンクタというらしい return ( a->second > b->second ); } int main (int argc, char **argv) { ifstream fin("/Users/yasuhisa/dbcls/txt/2297_51_2006.txt"); string str; char c; while (fin.get(c)) { str.push_back(c); // 文字列の連結 } MeCab::Tagger *tagger = MeCab::createTagger( "" ); const MeCab::Node *node = tagger->parseToNode( str.c_str() ); map<string, int> freq; map<string, int>::iterator it; for( node=node->next; node->next; node=node->next ){ vector<string> strvec = split( node->feature, "," ); if (strvec[0] == "名詞"){ string noun = strvec[6]; it = freq.find(noun); if (it != freq.end()){ it->second += 1; }else{ freq.insert(pair<string, int>(noun, 1)); } } } vector<map_freq_it> sorted; for(map_freq_it mfi = freq.begin(); mfi != freq.end(); ++mfi) sorted.push_back(mfi); sort(sorted.begin(), sorted.end(), compare); for(vec_stu_citer_t it = sorted.begin(); it != sorted.end(); ++it){ cout << (*it)->first << ","; cout << (*it)->second <<endl; } delete tagger; return 0; }
結果を見てみる。
/Users/yasuhisa/cpp% ./mecab | head -n 30 *,3062 細胞,243 極性,90 分子,59 制御,58 こと,54 シグナル,52 体,50 転写,48 分裂,46 因子,46 変異,45 発現,45 経路,37 側,35 非対称,33 移動,32 局在,32 図,30 機能,27 方向,27 化,27 よう,25 軸,25 索,24 ニューロン,24 核,23 関与,23 位置,22 割,21
苦労したところ、ちょっと身についたところ
難しい、とかではなくC++らしいやり方とかそもそもまだそんなにC++をしゃべれないとかなところだけど。
- 文字列のsplitがなくて困った
- RubyとかPerlみたいに付属じゃない
- boostを使うとどうにかできるとかできないとか
- typedefが何者かちょっと分かった
- 「map
::const_iterator」みたいな型を毎回書くのは面倒なので、この型の別名を付けてあげよう、というのがtypedefであると理解した
- 「map
- const_iteratorというのがあるのを覚えた
- がいまいちまだ分かっていない
- compareの「const map_freq_it&」の部分でなんでconstと「&」が必要なのかが分かっていない
- 日本語のファイルを読むところから苦労した
- 一文字ずつ読んだりしていて、マルチバイトがぶっこわれてしまっている、というところも気づいていなかった。id:mickey24に助けてもらった
- MeCabで形態素解析された特定のフィールドを取ってくる方法が分からなかった
- ベクトルのindexを指定しているんだけど、構造体っぽくどうにかならないのかなあ
- mapのvalueでsortする方法がうまいこといかなかった
- そういうわけで参考にさせてもらった
- mapをsort - GFSの興味ごととか
- STL mapをvalueでソートする方法
- あと分かりやすかったので、C++クックブックを購入
あとboostのインストール
この前はソースから自分で入れたんだけど、なんか今日はmacportで入れてみた。というわけで入っている場所が違う。
/opt/local/include/boost% ls accumulators date_time.hpp iostreams pointer_cast.hpp statechart algorithm detail is_placeholder.hpp pointer_to_other.hpp static_assert.hpp aligned_storage.hpp dynamic_bitset iterator pool static_warning.hpp any.hpp dynamic_bitset.hpp iterator.hpp preprocessor strong_typedef.hpp archive dynamic_bitset_fwd.hpp iterator_adaptors.hpp preprocessor.hpp system array.hpp dynamic_property_map.hpp lambda program_options test asio enable_shared_from_this.hpp last_value.hpp program_options.hpp thread asio.hpp exception lexical_cast.hpp progress.hpp thread.hpp assert.hpp exception.hpp limits.hpp property_map.hpp throw_exception.hpp assign exception_ptr.hpp logic property_map_iterator.hpp timer.hpp assign.hpp filesystem make_shared.hpp proto token_functions.hpp bimap filesystem.hpp math ptr_container token_iterator.hpp bimap.hpp foreach.hpp math_fwd.hpp python tokenizer.hpp bind format mem_fn.hpp python.hpp tr1 bind.hpp format.hpp memory_order.hpp random tuple blank.hpp function mpi random.hpp type.hpp blank_fwd.hpp function.hpp mpi.hpp range type_traits call_traits.hpp function_equal.hpp mpl range.hpp type_traits.hpp cast.hpp function_output_iterator.hpp multi_array rational.hpp typeof cerrno.hpp function_types multi_array.hpp ref.hpp units checked_delete.hpp functional multi_index regex unordered circular_buffer functional.hpp multi_index_container.hpp regex.h unordered_map.hpp circular_buffer.hpp fusion multi_index_container_fwd.hpp regex.hpp unordered_set.hpp circular_buffer_fwd.hpp generator_iterator.hpp next_prior.hpp regex_fwd.hpp utility compatibility get_pointer.hpp non_type.hpp scoped_array.hpp utility.hpp compressed_pair.hpp gil noncopyable.hpp scoped_ptr.hpp variant concept graph nondet_random.hpp serialization variant.hpp concept_archetype.hpp implicit_cast.hpp none.hpp shared_array.hpp vector_property_map.hpp concept_check indirect_reference.hpp none_t.hpp shared_container_iterator.hpp version.hpp concept_check.hpp integer numeric shared_ptr.hpp visit_each.hpp config integer.hpp operators.hpp signal.hpp wave config.hpp integer_fwd.hpp optional signals wave.hpp crc.hpp integer_traits.hpp optional.hpp signals.hpp weak_ptr.hpp cregex.hpp interprocess parameter smart_cast.hpp xpressive cstdint.hpp intrusive parameter.hpp smart_ptr.hpp cstdlib.hpp intrusive_ptr.hpp pending spirit current_function.hpp io pfto.hpp spirit.hpp date_time io_fwd.hpp pointee.hpp state_saver.hpp
環境設定のところはちゃんと変えてあげる必要があるでせう。
Effective Modern C++ ―C++11/14プログラムを進化させる42項目
- 作者: Scott Meyers,千住治郎
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/09/18
- メディア: 大型本
- この商品を含むブログ (7件) を見る