web-dev-qa-db-ja.com

文字列をトークンに分割するにはどうすればよいですか?

文字列がある場合

'x+13.5*10x-4e1'

どうすれば次のトークンのリストに分割できますか?

['x', '+', '13', '.', '5', '*', '10', 'x', '-', '4', 'e', '1']

現在、shlexモジュールを使用しています。

str = 'x+13.5*10x-4e1'
lexer = shlex.shlex(str)
tokenList = []
for token in lexer:
    tokenList.append(str(token))
return tokenList

しかし、これは戻ります:

['x', '+', '13', '.', '5', '*', '10x', '-', '4e1']

だから私は数字から文字を分割しようとしています。文字と数字の両方を含む文字列を取得して、何らかの方法でそれらを分割することを検討していますが、これを行う方法や、後で他の文字列と一緒にすべてをリストに追加する方法がわかりません。トークンが順番に並んでいることが重要であり、ネストされたリストを持つことはできません。

理想的な世界では、eとEは同じように文字として認識されないため、

'-4e1'

になります

['-', '4e1']

だが

'-4x1'

になります

['-', '4', 'x', '1']

誰か助けてもらえますか?

10
Martin Thetford

正規表現モジュールのsplit()関数を使用して、で分割します。

  • '\d+'-数字(数字)と
  • '\W+'-単語以外の文字:

コード:

import re

print([i for i in re.split(r'(\d+|\W+)', 'x+13.5*10x-4e1') if i])

出力:

['x', '+', '13', '.', '5', '*', '10', 'x', '-', '4', 'e', '1']

ドットを(式の浮動小数点数として)区切りたくない場合は、次のように使用する必要があります。

  • [\d.]+-数字またはドット文字(ただし、これにより次のように記述できます:13.5.5

コード:

print([i for i in re.split(r'([\d.]+|\W+)', 'x+13.5*10x-4e1') if i])

出力:

['x', '+', '13.5', '*', '10', 'x', '-', '4', 'e', '1']
15
Peter Varo

ここで提案されていない別の代替方法は、 nltk.tokenize モジュールを使用することです。

1
redrubia

さて、問題はそれほど単純ではないようです。堅牢な(ただし、残念ながらそれほど短くはない)ソリューションを取得するための良い方法は、フルウェイトのトークナイザーを作成するために Python Lex-Yacc を使用することだと思います。 Lex-Yaccはこれに対する一般的な(Pythonだけでなく)プラクティスであるため、単純な算術トークナイザー( このような )を作成するための準備が整った文法が存在する可能性があり、それらを特定のものに適合させる必要がありますニーズ。

0
Tigran Saluev