7

、、、、、および空白を区切り文字として使用し-て文字列を分割したいと考えています。空白でない限り、区切り文字を保持したい。+====+

私は次のコードでこれを達成しようとしました:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  return pattern.split(s)

print(tokenize("hello-+==== =+  there"))

私は出力が

['hello', '-', '+=', '==', '=', '=', '+', 'there']

しかし、私は得た

['hello', '-', '', '+=', '', '==', '', '=', '', None, '', '=', '', '+', '', None, 'there']

None余分なs と空の文字列がかなりあることを除いて、これはほとんど私が望んでいたものです。

なぜこのように動作するのですか? また、どうすれば変更して必要なものを取得できますか?

4

5 に答える 5

3

デフォルトでre.splitは、一致の間にある文字列のビットの配列を返します: (@Laurence Gonsalves が指摘しているように、これが主な用途です。)

['hello', '', '', '', '', '', '', '', 'there']

-+=+===などの間の空の文字列に注意してください。

ドキュメントで説明されているように、キャプチャ グループを使用しているため (つまり、(\-|\+\=|\=\=|\=|\+)代わりに を使用しているため(?:\-|\+\=|\=\=|\=|\+)、キャプチャ グループが一致するビットが点在しています。

['hello', '-', '', '+=', '', '==', '', '=', '', None, '', '=', '', '+', '', None, 'there']

None\s+パターンの半分が一致した場所に対応します。そのような場合、キャプチャ グループは何もキャプチャしませんでした。

re.split のドキュメントを見ると、一致の間に空の文字列を破棄する簡単な方法がわかりませんが、単純なリスト内包表記 (または必要に応じてfilterNone ) でs と空の文字列を簡単に破棄できます。

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  return [ x for x in pattern.split(s) if x ]

最後に 1 つ: これまで説明してきたことについては、これで問題なく動作しますが、プロジェクトの方向性によっては、適切な解析ライブラリに切り替えることをお勧めします。 Python wikiには、いくつかのオプションの概要が記載されています。

于 2013-05-10T18:54:39.407 に答える
2

なぜこのように振る舞うのですか?

re.split のドキュメントによると:

pattern でキャプチャ用の括弧が使用されている場合、パターン内のすべてのグループのテキストも結果のリストの一部として返されます。

これは文字通り正しいです。キャプチャ括弧が使用されている場合、すべてのグループのテキストが、一致するかどうかに関係なく返されます。何にも一致しなかったものは return None.

いつものようにsplit、2 つの連続する区切り文字は空の文字列を区切ると見なされるため、空の文字列が散在します。

必要なものを取得するにはどうすれば変更できますか?

最も簡単な解決策は、出力をフィルタリングすることです。

filter(None, pattern.split(s))
于 2013-05-10T19:01:23.643 に答える
2

おそらくre.findallあなたにもっと適しているでしょうか?

>>> re.findall(r'-|\+=|==|=|\+|[^-+=\s]+', "hello-+==== =+  there")
['hello', '-', '+=', '==', '=', '=', '+', 'there']
于 2013-05-10T19:08:01.213 に答える
1

このパターンは、あなたが望むものとより一致しています:

\s*(\-|\+\=|\=\=|\=|\+)\s*

ただし、予想どおり、各分割の間に空の文字列が表示されます。

于 2013-05-10T18:52:40.727 に答える
0

これを試して:

def tokenize(s):
  import re
  pattern = re.compile("(\-|\+\=|\=\=|\=|\+)|\s+")
  x = pattern.split(s)
  result = []
  for item in x:
    if item != '' and item != None:
      result.append(item)
  return result

print(tokenize("hello-+==== =+  there"))
于 2013-05-10T19:04:59.200 に答える