7

テキストデータ用の単純なパーサーを作成しようとしています。(テキストは、NLTK にパーサーがない言語です。)

基本的に、1 文字か 2 文字のプレフィックスの数には制限があります。単語には複数の接頭辞を付けることができます。また、1 文字または 2 文字のサフィックスの数も限られています。それらの間にあるものは何でも、単語の「ルート」でなければなりません。多くの単語には可能な解析が 1 つ以上あるため、単語を入力して、可能な解析のリストをタプル (プレフィックス、ルート、サフィックス) の形式で取得したいと考えています。

ただし、コードを構造化する方法がわかりません。私が試した1つの方法の例を貼り付けました(ダミーの英語データを使用して理解しやすくしました)が、明らかに正しくありません. 一つには、それは本当に醜くて冗長なので、もっと良い方法があると確信しています. 別の理由として、複数の接頭辞または接尾辞、または接頭辞と接尾辞の両方を持つ単語では機能しません。

何かご意見は?

prefixes = ['de','con']
suffixes = ['er','s']

def parser(word):
    poss_parses = []
    if word[0:2] in prefixes:
        poss_parses.append((word[0:2],word[2:],''))
    if word[0:3] in prefixes:
        poss_parses.append((word[0:3],word[3:],''))
    if word[-2:-1] in prefixes:
        poss_parses.append(('',word[:-2],word[-2:-1]))
    if word[-3:-1] in prefixes:
        poss_parses.append(('',word[:-3],word[-3:-1]))
    if word[0:2] in prefixes and word[-2:-1] in suffixes and len(word[2:-2])>2:
        poss_parses.append((word[0:2],word[2:-2],word[-2:-1]))
    if word[0:2] in prefixes and word[-3:-1] in suffixes and len(word[2:-3])>2:
        poss_parses.append((word[0:2],word[2:-2],word[-3:-1]))
    if word[0:3] in prefixes and word[-2:-1] in suffixes and len(word[3:-2])>2:
        poss_parses.append((word[0:2],word[2:-2],word[-2:-1]))
    if word[0:3] in prefixes and word[-3:-1] in suffixes and len(word[3:-3])>2:
        poss_parses.append((word[0:3],word[3:-2],word[-3:-1]))
    return poss_parses



>>> wordlist = ['construct','destructer','constructs','deconstructs']
>>> for w in wordlist:
...   parses = parser(w)
...   print w
...   for p in parses:
...     print p
... 
construct
('con', 'struct', '')
destructer
('de', 'structer', '')
constructs
('con', 'structs', '')
deconstructs
('de', 'constructs', '')
4

3 に答える 3

2

これが私の解決策です:

prefixes = ['de','con']
suffixes = ['er','s']

def parse(word):
    prefix = ''
    suffix = ''

    # find all prefixes
    found = True
    while found:
        found = False
        for p in prefixes:
            if word.startswith(p):
                prefix += p
                word = word[len(p):] # remove prefix from word
                found = True

    # find all suffixes
    found = True
    while found:
        found = False
        for s in suffixes:
            if word.endswith(s):
                suffix = s + suffix
                word = word[:-len(s)] # remove suffix from word
                found = True

    return (prefix, word, suffix)

print parse('construct')
print parse ('destructer')
print parse('deconstructs')
print parse('deconstructers')
print parse('deconstructser')
print parse('condestructser')

結果:

>>> 
('con', 'struct', '')
('de', 'struct', 'er')
('decon', 'struct', 's')
('decon', 'struct', 'ers')
('decon', 'struct', 'ser')
('conde', 'struct', 'ser')

アイデアは、すべてのプレフィックスをループしてそれらを集約し、同時に単語からそれらを削除することです。トリッキーな部分は、プレフィックスが定義されている順序によってプレフィックスが見つからない場合があるため、すべてのプレフィックスが見つかるまで反復を再呼び出しする必要があることです。

接尾辞についても同じことが言えますが、接尾辞の単語を逆の順序で作成する点が異なります。

于 2012-04-14T19:25:35.763 に答える
2

CodeChordsの人は私をこれに打ち負かしましたが、私のものは接頭辞と接尾辞をタプルとして与え(コンテキストを考えると多かれ少なかれ役立つかもしれません)、再帰を使用するので、とにかく投稿すると思いました。

class Parser():
    PREFIXES = ['de', 'con']
    SUFFIXES = ['er', 's']
    MINUMUM_STEM_LENGTH = 3

    @classmethod
    def prefixes(cls, word, internal=False):
        stem = word
        prefix = None
        for potential_prefix in cls.PREFIXES:
            if word.startswith(potential_prefix):
                prefix = potential_prefix
                stem = word[len(prefix):]
                if len(stem) >= cls.MINUMUM_STEM_LENGTH:
                    break
                else:
                    prefix = None
                    stem = word
        if prefix:
            others, stem = cls.prefixes(stem, True)
            others.append(prefix)
            return (others, stem) if internal else (reversed(others), stem)
        else:
            return [], stem

    @classmethod
    def suffixes(cls, word):
        suffix = None
        stem = word
        for potential_suffix in cls.SUFFIXES:
            if word.endswith(potential_suffix):
                suffix = potential_suffix
                stem = word[:-len(suffix)]
                if len(stem) >= cls.MINUMUM_STEM_LENGTH:
                    break
                else:
                    suffix = None
                    stem = word
        if suffix:
            others, stem = cls.suffixes(stem)
            others.append(suffix)
            return others, stem
        else:
            return [], stem

    @classmethod
    def parse(cls, word):
        prefixes, word = cls.prefixes(word)
        suffixes, word = cls.suffixes(word)
        return(tuple(prefixes), word, tuple(suffixes))

words = ['con', 'deAAers', 'deAAAers', 'construct', 'destructer', 'constructs', 'deconstructs', 'deconstructers']

parser = Parser()
for word in words:
    print(parser.parse(word))

それは私たちに与えます:

((), 'con', ())
(('de',), 'AAer', ('s',))
(('de',), 'AAA', ('er', 's'))
(('con',), 'struct', ())
(('de',), 'struct', ('er',))
(('con',), 'struct', ('s',))
(('de', 'con'), 'struct', ('s',))
(('de', 'con'), 'struct', ('er', 's'))

これは、単語を取得し、str.startswith()関数を使用してプレフィックスを検索することで機能します。プレフィックスのない単語に変換されるまでこれを再帰的に実行し、プレフィックスのリストを返します。

str.endswith()次に、明らかな理由で使用することを除いて、サフィックスに対して同様のことを行います。

于 2012-04-14T19:42:11.157 に答える
2

Pyparsing は、文字列のインデックス作成とトークンの抽出を独自の解析フレームワークにラップし、単純な算術構文を使用して解析定義を​​構築できるようにします。

wordlist = ['construct','destructer','constructs','deconstructs']

from pyparsing import StringEnd, oneOf, FollowedBy, Optional, ZeroOrMore, SkipTo

endOfString = StringEnd()
prefix = oneOf("de con")
suffix = oneOf("er s") + FollowedBy(endOfString)

word = (ZeroOrMore(prefix)("prefixes") + 
        SkipTo(suffix | endOfString)("root") + 
        Optional(suffix)("suffix"))

for wd in wordlist:
    print wd
    res = word.parseString(wd)
    print res.dump()
    print res.prefixes
    print res.root
    print res.suffix
    print

結果は、単純なリスト、名前付き属性を持つオブジェクト、または dict としてアクセスできる、ParseResults と呼ばれるリッチ オブジェクトで返されます。このプログラムの出力は次のとおりです。

construct
['con', 'struct']
- prefixes: ['con']
- root: struct
['con']
struct


destructer
['de', 'struct', 'er']
- prefixes: ['de']
- root: struct
- suffix: ['er']
['de']
struct
['er']

constructs
['con', 'struct', 's']
- prefixes: ['con']
- root: struct
- suffix: ['s']
['con']
struct
['s']

deconstructs
['de', 'con', 'struct', 's']
- prefixes: ['de', 'con']
- root: struct
- suffix: ['s']
['de', 'con']
struct
['s']
于 2012-04-14T22:28:52.003 に答える