2017-11-27 11 views
0

文字列を前処理しています。私は10k文字列置換の辞書を持っている(例えば、"John Lennon": "john_lennon")。他のすべての句読点をスペースで置き換えたいPython Regex:文字列置換のdictにある場合を除いて、アンダースコアとダッシュを削除します。

問題は、これらの文字列の置換にアンダースコアまたはハイフンが含まれているため、単語がこのdictのキーに含まれていない限り、句読点(完全停止を除く)をスペースで置き換えたいとします。私もでそれをやりたかった正規表現はテキストコーパスがかなり大きいのでボトルネックになる可能性があります。

これまでのところ、私が持っている:

import re 
input_str = "John Lennon: a musician, artist and activist." 
multi_words = dict((re.escape(k), v) for k, v in multi_words.items()) 
pattern = re.compile("|".join(multi_words.keys())) 
output_str = pattern.sub(lambda m: multi_words[re.escape(m.group(0))], input_str) 

これは、辞書のキーを使用して、すべての文字列を置換します。今度は同じパスで句読点を削除するだけです。これは、あなたがあなたの辞書内のエントリのように削除したい句読点を扱うことができる"john_lennon a musician artist and activist."

+1

本当に最後のフルストップを残してください。 – tripleee

+0

@トリプルPOは言った、 "私は句読点(完全な停止を除く)を置きたい。私はこれが最後の完全停止にも当てはまると思います。 – Alfe

+0

申し訳ありませんが、文章を区切るには完全な停止が必要です –

答えて

0

次の方法でそれを行うことができます構築された正規表現に1つの句読点文字にマッチするもう1つの代替を加える。一致が処理されると、ディクショナリのgetメソッドを使用して、辞書にない一致をスペースで置き換えることができます。ここでは[,:;_-]を使用しますが、おそらく他の文字を置き換えたいと考えています。

注:私はre.escapeへの呼び出しを正規表現の構築に移しました。すべてのマッチでそれを呼び出す必要がありません。

import re 
input_str = "John Lennon: a musician, artist and activist." 
pattern = re.compile(("|".join(map(re.escape, multi_words.keys())) + "|[,:;_-]+") 
output_str = pattern.sub(lambda m: multi_words.get(m.group(0), ' '), input_str) 
+0

これは素晴らしい、感謝しました! –

0

を返す必要があります:

pattern = re.compile("|".join(multi_words.keys()) + r'|_|-') 

multiwords['_'] = ' ' 
multiwords['-'] = ' ' 

そして、これらの発生があなたの鍵の言葉のように扱われます。

しかし、あなたのコードは特定の正規表現のセットに対してのみ機能することを思い出してください。キーにfoo.*barというパターンがあり、それがfoo123barのような文字列と一致する場合は、foo123barからre.escape()までを渡してから、multiword辞書で検索して、対応する値をキーに見つけることはできません。

私はエスケープすることをやめるべきだと思います。可変の入力にマッチする複雑な正規表現ではなく、固定された文字列だけがキーとして許可されることを明確にするためにコードにコメントする必要があります。

0

あなたが一致する項目の一部として設定された文字に(フルストップを除く)句読点を追加し、置換機能で別々に句読点やdictのキーを扱うことができます。

import re 
import string 

punctuation = string.punctuation.replace('.', '') 
pattern = re.compile("|".join(multi_words.keys())+ 
        "|[{}]".format(re.escape(punctuation))) 


def func(m): 
    m = m.group(0) 
    print(m, re.escape(m)) 
    if m in string.punctuation: 
     return '' 
    return multi_words[re.escape(m)] 

output_str = pattern.sub(func , input_str) 
print(output_str) 
# john_lennon a musician artist and activist. 
0

あなたが(?:alt1|alt2...|altN)|([^\w\s.]+)のような正規表現を使用し、グループ1(つまり、.以外の句読点)がマッチしたかどうかをチェックします。はいの場合は、空の文字列に置き換えます。

pattern = re.compile(r"(?:{})|([^\w\s.]+)".format("|".join(multi_words.keys()))) 
output_str = pattern.sub(lambda m: "" if m.group(1) else multi_words[re.escape(m.group(0))], input_str) 

Python demoを参照してください。

ノートについて_:あなたは[^\w\s.]は(ワード、空白や.文字以外の任意の文字にマッチする)、アンダースコア(単語文字)と一致しないと、あなたが追加する必要があるためr"(?:{})|([^\w\s.]+|_+)"を使用し、同様にそれを削除する必要がある場合それは別の代替手段として。

ユニコードに関する注意:Unicode文字列を扱う場合、Python 2.xでは、メソッドにre.Uまたはre.UNICODE修飾子フラグを渡します。

関連する問題