文字列の複数の部分文字列を置き換える方法は?


284

.replace関数を使用して複数の文字列を置き換えたいのですが。

私は現在持っています

string.replace("condition1", "")

しかし、次のようなものが欲しい

string.replace("condition1", "").replace("condition2", "text")

それは良い構文のようには感じられませんが

これを行う適切な方法は何ですか?grepを/正規表現であなたが行うことができますどのようにのようなの種類\1\2特定の検索文字列にフィールドを交換します


7
提供されているすべてのソリューションを試しましたか?どちらが速いですか?
tommy.carstensen 2013年

時間をかけて、さまざまなシナリオですべての回答をテストしました。stackoverflow.com/questions/59072514/…を
Pablo

1
正直なところ、他のすべてのアプローチよりも連鎖アプローチを好む。私は解決策を探している間にここに着陸し、あなたのものを使用しましたが、それはうまくいきます。
frakman1

@ frakman1 +1。これがこれ以上賛成されない理由はわかりません。他のすべてのメソッドはコードを読みにくくします。置き換える関数パス配列があった場合、これは機能します。しかし、連鎖メソッドは最も明確です(少なくとも静的な置換数がある場合)
IceFire

回答:


269

正規表現でトリックを実行する短い例を次に示します。

import re

rep = {"condition1": "", "condition2": "text"} # define desired replacements here

# use these three lines to do the replacement
rep = dict((re.escape(k), v) for k, v in rep.iteritems()) 
#Python 3 renamed dict.iteritems to dict.items so use rep.items() for latest versions
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)

例えば:

>>> pattern.sub(lambda m: rep[re.escape(m.group(0))], "(condition1) and --condition2--")
'() and --text--'

7
交換は1回のパスで行われます。
Andrew Clark

26
dkamins:それほど賢くはなく、本来あるべきほど賢くもありません( "|"で結合する前に、キーを正規表現でエスケープする必要があります)。なぜそれは過度に設計されていないのですか?この方法我々は1回のパスでそれを行うためのような衝突を避け、(速い=)、そして私たちは、同時にすべての置換を行う"spamham sha".replace("spam", "eggs").replace("sha","md5")こと"eggmd5m md5"の代わりに"eggsham md5"
羊飛行

8
@AndrewClarkラムダで最後の行で何が起こっているのか説明していただければ幸いです。
ミネラル

11
こんにちは、私はこのスニペットのより明確なバージョンで小さな要旨を作成しました。それはまた少し効率的であるべきです:gist.github.com/bgusach/a967e0587d6e01e889fd1d776c5f3729
bgusach

15
Python 3の場合、iteritems()の代わりにitems()を使用します。
Jangari 2017

127

あなたは素敵な小さなループ関数を作ることができます。

def replace_all(text, dic):
    for i, j in dic.iteritems():
        text = text.replace(i, j)
    return text

どこtextの完全な文字列で、dic辞書れる-各定義は、用語に試合を交換する文字列です。

:Pythonの3で、iteritems()置き換えられましたitems()


注意: Python辞書には、信頼できる反復順序がありません。このソリューションは、次の場合にのみ問題を解決します。

  • 交換の順番は関係ありません
  • 以前の交換の結果を変更することは交換に問題ありません

例えば:

d = { "cat": "dog", "dog": "pig"}
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, d)
print(my_sentence)

可能な出力#1:

「これは私のブタであり、これは私のブタです。」

可能な出力#2

「これは私の犬で、これは私の豚です。」

1つの可能な修正はOrderedDictを使用することです。

from collections import OrderedDict
def replace_all(text, dic):
    for i, j in dic.items():
        text = text.replace(i, j)
    return text
od = OrderedDict([("cat", "dog"), ("dog", "pig")])
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, od)
print(my_sentence)

出力:

"This is my pig and this is my pig."

注意#2:text文字列が大きすぎるか、辞書に多くのペアがある場合は非効率的です。


37
さまざまな置換を適用する順序が重要になります。標準の辞書を使用する代わりに、OrderedDict-または2タプルのリストを使用することを検討してください。
ナマケモノ

5
これにより、文字列が2回繰り返されます...パフォーマンスには適していません。
Valentin Lorentz

6
パフォーマンスに関しては、Valentinが言うよりも悪いです-それは、dic内のアイテムがある数だけテキストをトラバースします!「テキスト」が小さい場合は問題ありませんが、大きいテキストの場合はひどいです。
JDonner

3
これは、いくつかのケースに適したソリューションです。たとえば、サブ文字を2文字だけ入れたいのですが、置換キーがどの値とも一致しないため、それらの文字の順番は関係ありません。しかし、私はそれが何が起こっているのかを明確にすることを望んでいます。
Nathan Garabedian 2013年

5
最初の反復で新しく挿入されたテキストが2番目の反復で一致する可能性があるため、これにより予期しない結果が生じる可能性があることに注意してください。たとえば、すべての「A」を「B」に、すべての「B」を「C」に単純に置き換えようとすると、文字列「AB」は「BC」ではなく「CC」に変換されます。
Ambroz Bizjak 2013年

105

なぜこのような解決策がないのですか?

s = "The quick brown fox jumps over the lazy dog"
for r in (("brown", "red"), ("lazy", "quick")):
    s = s.replace(*r)

#output will be:  The quick red fox jumps over the quick dog

2
これは非常に便利で、シンプルで移植性があります。
細断

見栄えは良かったが、次のように正規表現に代わるものではない:for r in((r '\ s。'、 '。')、(r '\ s、'、 '、')):
Martin

2
1行にするには:ss = [s.replace(* r)for r in(( "brown"、 "red")、( "lazy"、 "quick"))] [0]
Mark K

94

これは、機能を使用したい場合に備えて、reduceを使用した最初のソリューションの変形です。:)

repls = {'hello' : 'goodbye', 'world' : 'earth'}
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls.iteritems(), s)

マルティノーのさらに優れたバージョン:

repls = ('hello', 'goodbye'), ('world', 'earth')
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls, s)

8
replsタプルのシーケンスを作成し、iteritems()呼び出しをなくす方が簡単でしょう。すなわちrepls = ('hello', 'goodbye'), ('world', 'earth')reduce(lambda a, kv: a.replace(*kv), repls, s)。また、3 Pythonでそのまま動作します
マーティ

いいね!python3を使用している場合は、iteritemsの代わりに項目を使用します(現在、dictsのものから削除されています)。
e.arbitrio 2016年

2
@martineau:reduce削除されて以来、これが python3で変更されずに機能することは真実ではありません。
ノルマニウス2018

5
@normanius:reduceまだしかし、それはの一部なされたものであり、存在するfunctoolsモジュール(参照ドキュメントを、私はそのまま言ったときに、私は同じコードが実行-ができ、確かそれが必要になるもので、Pythonの3)reduceとなっているimport、必要に応じて編それはもはや組み込みではないからです。
マルティノー2018

35

これは、FJとMiniQuarkのすばらしい回答のより簡潔な要約です。複数の文字列を同時に置換するために必要なのは、次の関数だけです。

def multiple_replace(string, rep_dict):
    pattern = re.compile("|".join([re.escape(k) for k in sorted(rep_dict,key=len,reverse=True)]), flags=re.DOTALL)
    return pattern.sub(lambda x: rep_dict[x.group(0)], string)

使用法:

>>>multiple_replace("Do you like cafe? No, I prefer tea.", {'cafe':'tea', 'tea':'cafe', 'like':'prefer'})
'Do you prefer tea? No, I prefer cafe.'

必要に応じて、この単純なものから始めて、独自の専用置換関数を作成できます。


1
これは良い解決策ですが、文字列を同時に置換しても、それらを順次実行(チェーニング)する場合とまったく同じ結果にはなりません。
martineau 2013

2
確かにrep_dict = {"but": "mut", "mutton": "lamb"}、文字列"button"を使用する"mutton"とコードで結果が得られますが"lamb"、置換が次々とチェーンされている場合はそれが得られます。
martineau 2013

2
これはこのコードの主要な機能であり、欠陥ではありません。連鎖置換では、私の例のように2つの単語を同時に相互に置き換えるという望ましい動作を実現できませんでした。
mmj

1
あなたがそれを必要としないなら、それは素晴らしい特徴に見えないでしょう。しかし、ここでは同時交換について話しているので、それが確かに主な機能です。「連鎖」置換を使用すると、例の出力はになりますがDo you prefer cafe? No, I prefer cafe.、これはまったく望ましくありません。
mmj 2013

@Davidがあなた自身の答えを書いてください、あなたの編集は過激すぎます
UmNyobe 2014年

29

私はこれをFJの優れた答えに基づいて構築しました:

import re

def multiple_replacer(*key_values):
    replace_dict = dict(key_values)
    replacement_function = lambda match: replace_dict[match.group(0)]
    pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
    return lambda string: pattern.sub(replacement_function, string)

def multiple_replace(string, *key_values):
    return multiple_replacer(*key_values)(string)

ワンショット使用法:

>>> replacements = (u"café", u"tea"), (u"tea", u"café"), (u"like", u"love")
>>> print multiple_replace(u"Do you like café? No, I prefer tea.", *replacements)
Do you love tea? No, I prefer café.

交換は1回のパスで行われるため、「café」は「tea」に変わりますが、「café」には戻りません。

同じ置換を何度も行う必要がある場合は、置換関数を簡単に作成できます。

>>> my_escaper = multiple_replacer(('"','\\"'), ('\t', '\\t'))
>>> many_many_strings = (u'This text will be escaped by "my_escaper"',
                       u'Does this work?\tYes it does',
                       u'And can we span\nmultiple lines?\t"Yes\twe\tcan!"')
>>> for line in many_many_strings:
...     print my_escaper(line)
... 
This text will be escaped by \"my_escaper\"
Does this work?\tYes it does
And can we span
multiple lines?\t\"Yes\twe\tcan!\"

改善点:

  • コードを関数に変えた
  • 複数行のサポートを追加
  • エスケープのバグを修正
  • 特定の複数の置換のための関数を作成するのは簡単

楽しい!:-)


1
誰かが私のようなpython noobsについてこのステップバイステップで説明できますか?
ジュリアンスアレス

ここではpython noobの仲間なので、理解するには不完全なショットを撮ります。key_valuesを置換するもの(「|」で結合されたキー)とロジック(一致がキーの場合は戻り値)に分解します。正規表現パーサー(キーを検索し、指定されたロジックを使用する「パターン」)を作成します-これをラムダ関数でラップして返します。私が今調べているもの:re.M、そして置換ロジックのためのラムダの必要性。
フォックス

1
@Foxわかりました。ラムダを使用する代わりに関数を定義することもできます。それは単にコードを短くするためです。ただし、pattern.subは1つのパラメータ(置き換えるテキスト)のみを持つ関数を想定しているため、関数はにアクセスする必要がありますreplace_dictre.M複数行の置換を許可します(ドキュメント:docs.python.org/2/library/re.html#re.Mで詳しく説明されています)。
MiniQuark

22

文字列テンプレートの使い方を提案したいと思います。置き換える文字列を辞書に置くだけで、すべてが設定されます!docs.python.orgの

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
[...]
ValueError: Invalid placeholder in string: line 1, col 10
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
[...]
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'

見栄えは良いですが、で提供されていないキーを追加substituteすると例外が発生するため、ユーザーからテンプレートを取得するときは注意してください。
Bart Friederichs

2
このアプローチの欠点は、テンプレートに置き換えられる$ stringsがすべて含まれている必要があることです。ここを
RolfBly

17

私の場合、一意のキーを名前で簡単に置き換える必要があったので、これを考えました:

a = 'This is a test string.'
b = {'i': 'I', 's': 'S'}
for x,y in b.items():
    a = a.replace(x, y)
>>> a
'ThIS IS a teSt StrIng.'

3
これは、代替の衝突がない限り機能します。あなたと交換iしたs場合、あなたは奇妙な行動をするでしょう。
bgusach

1
順序が重要な場合は、上記のdictの代わりに配列を使用できます。 b = [ ['i', 'Z'], ['s', 'Y'] ]; for x,y in (b): a = a.replace(x, y) 次に、配列ペアを慎重に順序付けすると、replace()を再帰的に行わないようにすることができます。
CODE-REaD 2016年

Python 3.7.0から、dictsは順序を維持するようです。私はそれをテストし、それは、Python 3最新の安定と私のマシン上で順番に動作します
ジェームズ・コス

15

開始Python 3.8、との導入の代入式(PEP 572) :=オペレータ)、我々はリスト内包内置換を適用することができます。

# text = "The quick brown fox jumps over the lazy dog"
# replacements = [("brown", "red"), ("lazy", "quick")]
[text := text.replace(a, b) for a, b in replacements]
# text = 'The quick red fox jumps over the quick dog'

ループで置換を使用するよりも効率的かどうか知っていますか?すべての回答のパフォーマンスをテストしていますが、3.8はまだありません。
パブロ

出力をリストで取得するのはなぜですか?
johnrao07

1
@ johnrao07まあリスト内包表記はリストを作成します。そのため、この場合はを取得し['The quick red fox jumps over the lazy dog', 'The quick red fox jumps over the quick dog']ます。ただし、代入式(text := text.replace)も、を変更textすることにより、の新しいバージョンを繰り返し作成します。リストを理解した後、text変更されたテキストを含む変数を使用できます。
ザビエルギホ

1
の新しいバージョンをtextワンライナーとして返したい場合は、リスト内包表記の最後の要素を抽出する[text := text.replace(a, b) for a, b in replacements][-1](に注意[-1])も使用できます。つまり、の最後のバージョンですtext
ザビエルギホ

13

ここに私の$ 0.02。これはAndrew Clarkの回答に基づいており、少しだけ明確です。また、置換する文字列が別の文字列の部分文字列である場合もカバーします(長い文字列が優先されます)。

def multireplace(string, replacements):
    """
    Given a string and a replacement map, it returns the replaced string.

    :param str string: string to execute replacements on
    :param dict replacements: replacement dictionary {value to find: value to replace}
    :rtype: str

    """
    # Place longer ones first to keep shorter substrings from matching
    # where the longer ones should take place
    # For instance given the replacements {'ab': 'AB', 'abc': 'ABC'} against 
    # the string 'hey abc', it should produce 'hey ABC' and not 'hey ABc'
    substrs = sorted(replacements, key=len, reverse=True)

    # Create a big OR regex that matches any of the substrings to replace
    regexp = re.compile('|'.join(map(re.escape, substrs)))

    # For each match, look up the new string in the replacements
    return regexp.sub(lambda match: replacements[match.group(0)], string)

これはこの要旨であり、提案があれば自由に変更してください。


1
正規表現は長さの降順で並べ替えて|で結合することによりすべてのキーから構築されるため、これは代わりに受け入れられた答えであるはずです。正規表現代替演算子。また、選択肢がある場合は、可能な限り最も長い選択肢が選択されるように、並べ替えが必要です。
Sachin S

ソートのおかげで、これが最善の解決策であることに同意します。並べ替えは別として、私の元の答えと同じなので、このような重要な機能を見逃さないように、私のソリューションの並べ替えも借りました。
mmj

6

置換する文字列を正規表現にできるソリューションが必要でした。たとえば、複数の空白文字を1つの空白文字に置き換えることで長いテキストを正規化するのに役立ちます。MiniQuarkやmmjを含む他の人からの一連の回答に基づいて、これが私が思いついたものです。

def multiple_replace(string, reps, re_flags = 0):
    """ Transforms string, replacing keys from re_str_dict with values.
    reps: dictionary, or list of key-value pairs (to enforce ordering;
          earlier items have higher priority).
          Keys are used as regular expressions.
    re_flags: interpretation of regular expressions, such as re.DOTALL
    """
    if isinstance(reps, dict):
        reps = reps.items()
    pattern = re.compile("|".join("(?P<_%d>%s)" % (i, re_str[0])
                                  for i, re_str in enumerate(reps)),
                         re_flags)
    return pattern.sub(lambda x: reps[int(x.lastgroup[1:])][1], string)

それは他の答えで与えられた例のために働きます、例えば:

>>> multiple_replace("(condition1) and --condition2--",
...                  {"condition1": "", "condition2": "text"})
'() and --text--'

>>> multiple_replace('hello, world', {'hello' : 'goodbye', 'world' : 'earth'})
'goodbye, earth'

>>> multiple_replace("Do you like cafe? No, I prefer tea.",
...                  {'cafe': 'tea', 'tea': 'cafe', 'like': 'prefer'})
'Do you prefer tea? No, I prefer cafe.'

私にとっての主なことは、たとえば単語全体を置き換えるために、または空白を正規化するために、正規表現も使用できることです。

>>> s = "I don't want to change this name:\n  Philip II of Spain"
>>> re_str_dict = {r'\bI\b': 'You', r'[\n\t ]+': ' '}
>>> multiple_replace(s, re_str_dict)
"You don't want to change this name: Philip II of Spain"

辞書キーを通常の文字列として使用したい場合は、たとえば次の関数を使用してmultiple_replaceを呼び出す前に、それらをエスケープできます。

def escape_keys(d):
    """ transform dictionary d by applying re.escape to the keys """
    return dict((re.escape(k), v) for k, v in d.items())

>>> multiple_replace(s, escape_keys(re_str_dict))
"I don't want to change this name:\n  Philip II of Spain"

次の関数は、辞書のキーから誤った正規表現を見つけるのに役立ちます(multiple_replaceからのエラーメッセージはあまりわかりません)。

def check_re_list(re_list):
    """ Checks if each regular expression in list is well-formed. """
    for i, e in enumerate(re_list):
        try:
            re.compile(e)
        except (TypeError, re.error):
            print("Invalid regular expression string "
                  "at position {}: '{}'".format(i, e))

>>> check_re_list(re_str_dict.keys())

置換はチェーンされず、同時に実行されることに注意してください。これにより、実行できることを制限することなく、より効率的になります。連鎖の効果を模倣するには、文字列と置換のペアをさらに追加して、ペアの期待される順序を確認する必要がある場合があります。

>>> multiple_replace("button", {"but": "mut", "mutton": "lamb"})
'mutton'
>>> multiple_replace("button", [("button", "lamb"),
...                             ("but", "mut"), ("mutton", "lamb")])
'lamb'

これはいいです、ありがとう。置換でバックリファレンスを使用できるように改善できますか?それを追加する方法はすぐにはわかりません。
cmarqu 2017

上記の私の質問への答えは、stackoverflow.com
questions / 45630940 /…

4

これは、小さな文字列を多数置換した長い文字列でより効率的なサンプルです。

source = "Here is foo, it does moo!"

replacements = {
    'is': 'was', # replace 'is' with 'was'
    'does': 'did',
    '!': '?'
}

def replace(source, replacements):
    finder = re.compile("|".join(re.escape(k) for k in replacements.keys())) # matches every string we want replaced
    result = []
    pos = 0
    while True:
        match = finder.search(source, pos)
        if match:
            # cut off the part up until match
            result.append(source[pos : match.start()])
            # cut off the matched part and replace it in place
            result.append(replacements[source[match.start() : match.end()]])
            pos = match.end()
        else:
            # the rest after the last match
            result.append(source[pos:])
            break
    return "".join(result)

print replace(source, replacements)

ポイントは、長い文字列の多くの連結を回避することです。ソース文字列を断片に細断し、リストを形成するときに一部の断片を置き換えてから、全体を文字列に結合します。


2

あなたは本当にこの方法でそれをするべきではありませんが、私はそれがあまりにもクールすぎると思います:

>>> replacements = {'cond1':'text1', 'cond2':'text2'}
>>> cmd = 'answer = s'
>>> for k,v in replacements.iteritems():
>>>     cmd += ".replace(%s, %s)" %(k,v)
>>> exec(cmd)

さて、answer順番にすべての置換の結果です

繰り返しますが、これは非常にハックであり、定期的に使用する必要があるものではありません。しかし、必要に応じてこのようなことを実行できることを知っておくのは良いことです。


2

私もこの問題に苦しんでいました。多くの置換を行うと、正規表現は困難になり、ループstring.replace(実験条件では)よりも約4倍遅くなります。

Flashtextライブラリを使用してみてください(ブログの投稿はこちらGithubはこちら)。私の場合、各ドキュメントで1.8秒から0.015秒(正規表現は7.7秒かかりました)2桁以上高速でした。

上記のリンクで使用例を見つけるのは簡単ですが、これは実用的な例です。

    from flashtext import KeywordProcessor
    self.processor = KeywordProcessor(case_sensitive=False)
    for k, v in self.my_dict.items():
        self.processor.add_keyword(k, v)
    new_string = self.processor.replace_keywords(string)

Flashtextは単一パスで置換を行うことに注意してください(a- > bおよびb-> cが 'a'を 'c'に変換するのを避けるため)。Flashtextは単語全体も検索します(したがって、「is」は「th is」と一致しません)。ターゲットが複数の単語である場合は問題なく機能します(「This is」を「Hello」に置き換えます)。


HTMLタグを置き換える必要がある場合、これはどのように機能しますか?例えば、置き換える<p>/n。私はあなたのアプローチを試しましたが、タグ付きのフラッシュテキストはそれを解析していないようですか?
alias51

1
なぜ期待どおりに動作しないのかわかりません。1つの可能性は、これらのタグがスペースで区切られていないことです。Flashtextが単語全体を探すことを覚えておいてください。これを回避する方法は、最初に単純な置換を使用して、「Hi <p> there」が「Hi <p> there」になるようにすることです。完了したら、不要なスペースを削除するように注意する必要があります(これも単純に置き換えますか?)。お役に立てば幸いです。
パブロ

ありがとう、単語の終わりを設定<>てマークすることはできますか(ただし、置換に含まれます)?
alias51

1
「単語」はスペースのみでマークされていると思います。「KeywordProcessor」で設定できるオプションのパラメータがいくつかある可能性があります。それ以外の場合は、上記のアプローチを検討してください。「<」を「<」で置き換え、Flashtextを適用してから元に戻します(たとえば、「<」を「<」に、「\ n」を「\ n」で機能する場合があります)。
パブロ

2

この質問には、完全性のために単一行の再帰的ラムダ関数の答えが必要だと思います。だからそこに:

>>> mrep = lambda s, d: s if not d else mrep(s.replace(*d.popitem()), d)

使用法:

>>> mrep('abcabc', {'a': '1', 'c': '2'})
'1b21b2'

ノート:

  • これは入力辞書を消費します。
  • Python dictは、3.6の時点でキーの順序を保持します。他の回答の対応する警告は、もう関係ありません。後方互換性のために、タプルベースのバージョンに頼ることができます:
>>> mrep = lambda s, d: s if not d else mrep(s.replace(*d.pop()), d)
>>> mrep('abcabc', [('a', '1'), ('c', '2')])

注: Pythonのすべての再帰関数と同様に、再帰の深さが大きすぎる(つまり、置換辞書が大きすぎる)と、エラーが発生します。たとえば、こちらをご覧ください。


大きな辞書を使用すると、RecursionErrorが発生します。
パブロ

@パブロ興味深い。なんて大きい?これはすべての再帰関数で発生することに注意してください。例はこちらをご覧ください:stackoverflow.com/questions/3323001/…–
mcsoini

置換の私の辞書には、これまでstring.replaceを使用している... 100kの条件に近いはるかに最善のアプローチ。
Pablo

1
その場合、@ Pabloは再帰関数を使用できません。一般的にsys.getrecursionlimit()、最大1000です。ループなどを使用するか、置換を単純化してみてください。
mcsoini

ええ、本当にここには近道はありません。
Pablo

1

速度についてはわかりませんが、これは私の平凡なクイックフィックスです。

reduce(lambda a, b: a.replace(*b)
    , [('o','W'), ('t','X')] #iterable of pairs: (oldval, newval)
    , 'tomato' #The string from which to replace values
    )

...しかし、私は上記の#1正規表現の答えが好きです。注-1つの新しい値が別の値の部分文字列である場合、操作は可換ではありません。


1

pandasライブラリと、replace完全一致と正規表現の置換の両方をサポートする関数を使用できます。例えば:

df = pd.DataFrame({'text': ['Billy is going to visit Rome in November', 'I was born in 10/10/2010', 'I will be there at 20:00']})

to_replace=['Billy','Rome','January|February|March|April|May|June|July|August|September|October|November|December', '\d{2}:\d{2}', '\d{2}/\d{2}/\d{4}']
replace_with=['name','city','month','time', 'date']

print(df.text.replace(to_replace, replace_with, regex=True))

そして、変更されたテキストは次のとおりです。

0    name is going to visit city in month
1                      I was born in date
2                 I will be there at time

ここで例を見つけることができます。テキストの置換は、リストに表示される順序で行われることに注意してください


1

1文字だけを置き換えるには、translateおよびを使用しstr.maketransます。これが私のお気に入りの方法です。

tl; dr> result_string = your_string.translate(str.maketrans(dict_mapping))


デモ

my_string = 'This is a test string.'
dict_mapping = {'i': 's', 's': 'S'}
result_good = my_string.translate(str.maketrans(dict_mapping))
result_bad = my_string
for x, y in dict_mapping.items():
    result_bad = result_bad.replace(x, y)
print(result_good)  # ThsS sS a teSt Strsng.
print(result_bad)   # ThSS SS a teSt StrSng.

0

Andrewの貴重な答えから始めて、ファイルからディクショナリを読み込み、開いたフォルダのすべてのファイルを精緻化して置換を行うスクリプトを開発しました。スクリプトは、セパレーターを設定できる外部ファイルからマッピングをロードします。私は初心者ですが、このスクリプトは複数のファイルで複数の置換を行うときに非常に便利です。秒で1000以上のエントリを持つディクショナリをロードしました。エレガントではありませんが、うまくいきました

import glob
import re

mapfile = input("Enter map file name with extension eg. codifica.txt: ")
sep = input("Enter map file column separator eg. |: ")
mask = input("Enter search mask with extension eg. 2010*txt for all files to be processed: ")
suff = input("Enter suffix with extension eg. _NEW.txt for newly generated files: ")

rep = {} # creation of empy dictionary

with open(mapfile) as temprep: # loading of definitions in the dictionary using input file, separator is prompted
    for line in temprep:
        (key, val) = line.strip('\n').split(sep)
        rep[key] = val

for filename in glob.iglob(mask): # recursion on all the files with the mask prompted

    with open (filename, "r") as textfile: # load each file in the variable text
        text = textfile.read()

        # start replacement
        #rep = dict((re.escape(k), v) for k, v in rep.items()) commented to enable the use in the mapping of re reserved characters
        pattern = re.compile("|".join(rep.keys()))
        text = pattern.sub(lambda m: rep[m.group(0)], text)

        #write of te output files with the prompted suffice
        target = open(filename[:-4]+"_NEW.txt", "w")
        target.write(text)
        target.close()

0

これが私の問題の解決策です。私はそれをチャットボットで使用して、異なる単語を一度に置き換えました。

def mass_replace(text, dct):
    new_string = ""
    old_string = text
    while len(old_string) > 0:
        s = ""
        sk = ""
        for k in dct.keys():
            if old_string.startswith(k):
                s = dct[k]
                sk = k
        if s:
            new_string+=s
            old_string = old_string[len(sk):]
        else:
            new_string+=old_string[0]
            old_string = old_string[1:]
    return new_string

print mass_replace("The dog hunts the cat", {"dog":"cat", "cat":"dog"})

これは The cat hunts the dog


0

別の例:入力リスト

error_list = ['[br]', '[ex]', 'Something']
words = ['how', 'much[ex]', 'is[br]', 'the', 'fish[br]', 'noSomething', 'really']

望ましい出力は

words = ['how', 'much', 'is', 'the', 'fish', 'no', 'really']

コード:

[n[0][0] if len(n[0]) else n[1] for n in [[[w.replace(e,"") for e in error_list if e in w],w] for w in words]] 

-2

またはちょうど速いハックのために:

for line in to_read:
    read_buffer = line              
    stripped_buffer1 = read_buffer.replace("term1", " ")
    stripped_buffer2 = stripped_buffer1.replace("term2", " ")
    write_to_file = to_write.write(stripped_buffer2)

-2

辞書でそれを行う別の方法を次に示します。

listA="The cat jumped over the house".split()
modify = {word:word for number,word in enumerate(listA)}
modify["cat"],modify["jumped"]="dog","walked"
print " ".join(modify[x] for x in listA)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.