鋭い方に「何をもって基礎的と言ってんだ」と突っ込まれそうですが,ここでは「言語処理100本ノック 2015の1章をを自力で解けるような文字列処理の知識を身に着ける」という意味で「基礎的な」という表現を使わさせていただいています.
なので,今回の投稿は言語処理100本ノック 2015の1章を解くことを強く意識した投稿になります.
文章から単語を分離する
扱う文字列としてスペース( ),コンマ(,),ピリオド(.)を含む一般の文章を考えます.日本語の文章でなく英語の文章を扱っていることにご注意ください.
句読点のない文章を,単語に分離する
s = 'This is a sample sentence' a = s.split() print(a)
実行結果は [‘This’, ‘is’, ‘an’, ‘sample’, ‘sentence’] となります.
「s.split()」という指示で「sという名前の文字列を,スペースを境目として分離します」という意味になります.このとき a はリスト型になります.print(a)の結果からお分かりの通り,[‘This’, ‘is’, ‘an’, ‘sample’, ‘sentence’] のようにstring型を要素として持つようなリストがa(=s.split())になっています.
句読点のある文章を,単語に分離する
s = 'This is a sample sentence. And, this is second sentence.' b = s.replace(',','') c = b.replace('.','') a = c.split() print(a)
実行結果は,[‘This’, ‘is’, ‘a’, ‘sample’, ‘sentence’, ‘And’, ‘this’, ‘is’, ‘second’, ‘sentence’] となり,確かにコンパとピリオドを削除した状態で単語を分離できました.
コードの説明です.先ほどの例ではあくまでも空白を基準に分けたため,2行目で「a = s.split()」とするだけではカンマとピリオドがそのまま残ってしまいます,つまり,本当の意味で単語に分離ができていません.コンマとピリオドを削除する方法として今回は文字列を置き換える「replace」という機能を用いています.
s2 = s1.replace('x', 'y')
と書くことで,「s1に代入されている文字列の中のすべてのxという文字をyという文字に変えて,それをs2に代入する」ことを行っています.上の例をみると,二行目ではxがカンマ(,)に対応し,yが空っぽになっています.これでカンマの削除が行えるのです.よってbにはsからカンマが除かれた文が収められています.同様にして,cにはbからピリオドが除かれた文が収められています.ここまででもとの文章sからコンマとピリオドが除かれた文cが作成されたので,これを先ほど習ったsplit()の機能を使って単語に分解すればオッケーです.
おまけ:機能の連続使用
ちなみに上の式は次のようにするともう少し短く書くこともできます.どういう仕組みなのか,さっきの場合とよく比べてみましょう.
s = 'This is a sample sentence. And, this is second sentence' a = s.replace(',','').replace('.','').split() print(a)
右端の文字の削除
replaceで文字を消すと,文字列の中のすべての指定された文字が変わってしまいます.一般に文章を空白で分けた際に,コンマやピリオドは分けた塊の一番右側に来ます.それを利用して「文の後ろのピリオドを取り除く」ということを次のようにして行うことができます.
s = 'This is a sample sentence. And, this is second sentence.' print( s.rstrip('.') )
「s.rstrip(‘,’)」とすることで「sという変数に格納されている文字列の右端にあるピリオド(.)をはぎ取ってください」という指示です.実行結果は文末の「sentence.」が「sentence」に代わるだけです.
辞書
python には辞書(ディクショナリー, dictionary)という型があります.日本語の国語辞書は「見出し語:見出し語の意味」というペアになっていますが,python の辞書の要素も「見出し語:値」のような形をしています.見出し語(keyともいう)に入る型は様々なものが可能です.
空の辞書の作成
dict = {}
波括弧を使ったこの一行で,dict という名前の付いた辞書(まだ中身は空っぽ)が作成されます.
辞書の要素を追加
dict = {} dict['nenrei'] = 12
このように書くことで,dictという名前の辞書に「’nenrei’:12」という「文字:整数」のペアが登録されます.
辞書についての補足
ここでは言語処理100本ノック 2015を解くことを目標に投稿を書いているため,初心者に誤解されることなく理解しやすいように書いているつもりです.なので辞書についてはこれ以上踏み込みませんが,実は本当のpythonの辞書はもっと複雑です.詳しく知りたい方は,公式ドキュメントに目を通してみていただければと思います.
Python 公式ドキュメント – マッピング型(http://docs.python.jp/3.5/library/stdtypes.html#dict)
集合(set)
リストは重複が許されました.例えば
L = ['a','a','b','b','c']
のようにすると,文字列の要素を5つもつLという名前のリストが作成されます.’a’という同じ要素を持っていても,ちゃんとそれをL[0]としてのaとL[1]としてのaとして区別しています.しかし,今回扱う「集合」という型では,同じ要素は区別しないリスト(のようなもの)になります.それだけでなく,要素に番号付けもされていません.次の操作を見ながらその特徴を理解してください.
リストからセットへの変換
いきなりですが,上で作ったリストを集合に変換してみましょう.
L = ['a','a','b','b','c'] X = set(L) print(X)
実行結果は{‘a’, ‘b’, ‘c’}となります.リストのときにあった重複がなくなっていることがわかります.続けて次のコードを実行してみてください.
L = ['a','a','b','b','c'] print( L[0] ) X = set(L) print( X[0] )
L[0]は’a’と出力してくれますが,最後で「TypeError: ‘set’ object does not support indexing」のようなエラーが出ると思います.つまり,集合には「何番目の要素」という考え方はなくなっているのですね.ただの要素の集まりというだけなのです.
集合間の演算
数学で扱う集合での演算と同じく共通部分([math]A\cap B[/math]),和集合([math]A\cup B[/math]),差集合([math]A\backslash B[/math])を,pythonでは簡単に扱うことができます.タイトルとコードと計算結果だけを羅列してもわかっていただけると思います.
共通部分
A = {1,2,3,4,5,6,7,8} B = {6,7,8,9,10,11,12} print(A&B)
実行結果は,自分の環境では{8,6,7}です.集合では順番は関係ないことに注意しましょう.
和集合
A = {1,2,3,4,5,6,7,8} B = {6,7,8,9,10,11,12} print(A|B)
実行結果は{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}です.
差集合
A = {1,2,3,4,5,6,7,8} B = {6,7,8,9,10,11,12} print(A-B)
実行結果は{1, 2, 3, 4, 5}です.
約束守れませんでした,ごめんなさい
「そういやお前,前の投稿の最後で次のようなことを書いたな.」
次の投稿で文字列(文章)の処理について扱う予定で,それさえクリアすれば 1章(09まで)は自力で解けるような投稿を書こうと思います.というか書きます.
「お前の投稿位置から追って100%理解したんだが,まだ解けない問題があるんですわ.どう落としm」すんません.マジすんません.
実際書いてみた結果,まだ条件分岐(if文)と標準入力の内容だけ残ってしまいました...こっちの投稿に押し込んでもよいのですが,そうするとボリュームが増えてしまうので,この二つのテーマについてはまた新しい投稿で扱おうと思います.
読んでいただいて本当にありがとうございます.