stkblog

白血病と関係ないことを書きます なにかあったら教えて下さい

言語処理100本ノックやった 03-06 #python

これのつづきです

steek.hatenablog.com

たまにチラ見させてもらったりしてます

kiito.hatenablog.com
qiita.com

前回のちょっと改良

#03 円周率

前回の解答

str = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
str = ''.join([s for s in str if s not in [',', '.']])
list = [len(i) for i in list(str.split(' '))]
print list #[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9]

にしたけど、ピリオドやカンマを取り除くのは .strip() を使うのがいいっぽい。split() で単語ごとにわけたあと strip() の文字列の左右端からかっこの中身を取り除く。ストリップとスプリット語感が似てて困る。
上のは str を list にしてそれを str にして list にしててダサかった

改良版

str = "Now I need a drink, alcoholic of course, after the heavy lectures involving quantum mechanics."
words = str.split()
ans = [len(word.strip(',.')) for word in words]
print ans

#04 元素記号

前回の回答

str = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
atom = dict()
cnt = 0
for item in str.split():
    cnt += 1
    if cnt in [1, 5, 6, 7, 8, 9, 15, 16, 19]:
        atom[item[0]] = cnt
    else:
        atom[item[:2]] = cnt
print atom

enumerate を使えば自分でカウンターを用意しなくてもいいらしい。
http://docs.python.jp/2/library/functions.html#enumerate


改良版

str = "Hi He Lied Because Boron Could Not Oxidize Fluorine. New Nations Might Also Sign Peace Security Clause. Arthur King Can."
str = str.split()
atom = dict()
for i, elem in enumerate(str):
    if i+1 in [1, 5, 6, 7, 8, 9, 15, 16, 19]:
        atom[elem[0]] = i+1
    else:
        atom[elem[:2]] = i+1
print atom

あんまり変わんないか。

先へ進む

#05 n-gram

与えられたシーケンス(文字列やリストなど)からn-gramを作る関数

最初の解答
from itertools import combinations
def ngram(inp, n):
    ans = []
    subs = combinations(xrange(len(inp)), n)
    for sub in subs:
        ans.append((inp[sub[0]], inp[sub[1]]))
    return ans

str = "I am an NLPer"
print ngram(str.split(), 2)
#[('I', 'am'), ('I', 'an'), ('I', 'NLPer'), ('am', 'an'), ('am', 'NLPer'), ('an', 'NLPer')]
print ngram([s for s in str if s != ' '], 2)

これを書いたあと、n-gram ってこんなんだっけ?と思って調べる

In the fields of computational linguistics and probability, an n-gram is a *contiguous* sequence of n items from a given sequence of text or speech.

https://en.wikipedia.org/wiki/N-gram

あ、すいませんでした
任意の2組を取るってことではなかった

気を取り直して
def ngram(inp, n):
    ans = []
    for i in xrange(len(inp) -n +1):
        ans.append(tuple(inp[i:i+n]))
    return ans

str = "I am an NLPer"
print ngram(str.split(), 2)
# [('I', 'am'), ('am', 'an'), ('an', 'NLPer')]
print ngram([s for s in str if s != ' '], 2)
# [('I', 'a'), ('a', 'm'), ('m', 'a'), ('a', 'n'), ('n', 'N'), ('N', 'L'), ('L', 'P'), ('P', 'e'), ('e', 'r')]

n個の並びを順番に append しただけ

#06 集合

"paraparaparadise"と"paragraph"に含まれる文字bi-gramの集合をそれぞれ,XとYとして求め、XとYの和集合、積集合、差集合を求め、さらに,'se'というbi-gramがXおよびYに含まれるかどうかを調べる

def ngram(inp, n):
    ans = []
    for i in xrange(len(inp) -n +1):
        ans.append(tuple(inp[i:i+n]))
    return ans
#上と同じ
prd = "paraparaparadise"
prg = "paragraph"
prd_2gram = ngram([s for s in prd if s != ' '], 2)
prg_2gram = ngram([s for s in prg if s != ' '], 2)

X, Y = map(set, [prd_2gram, prg_2gram])
union = X.union(Y)
intersection = X.intersection(Y)
dif1 = X.difference(Y)
dif2 = Y.difference(X)

print 'union-> ', union
# union->  set([('g', 'r'), ('p', 'h'), ('p', 'a'), ('s', 'e'), ('a', 'p'), ('a', 'g'), ('a', 'd'), ('i', 's'), ('r', 'a'), ('a', 'r'), ('d', 'i')])
print 'intersection-> ', intersection
# intersection->  set([('a', 'p'), ('r', 'a'), ('p', 'a'), ('a', 'r')])
print 'X-Y-> ', dif1 # A-B->  set([('a', 'd'), ('s', 'e'), ('d', 'i'), ('i', 's')])
print 'Y-X-> ', dif2 # B-A->  set([('g', 'r'), ('a', 'g'), ('p', 'h')])
print "'se' is in X" if ('s', 'e') in X else "'se' is not in X" # 'se' is in X
print "'se' is in Y" if ('s', 'e') in Y else "'se' is not in Y" # 'se' is not in Y

集合はそのまま set()
union intersection difference もそのまま
リストの中身に合わせて ('s', 'e') が入ってるかどうか聞く。そのまま。

X.union(Y) とかの表記、非対称な感じで気持ち悪いなと思ってたら

union = X | Y
intersection = X & Y
dif1 = X-Y
dif2 = Y-X

でよかったらしい。わかりやすすぎる

今日はこんな感じです


www.cl.ecei.tohoku.ac.jp