ฉันต้องการโซลูชันที่สตริงที่จะถูกแทนที่อาจเป็นนิพจน์ทั่วไปตัวอย่างเช่นเพื่อช่วยในการทำให้ข้อความธรรมดามีความยาวโดยการแทนที่อักขระช่องว่างจำนวนมากด้วยอักขระเดียว การสร้างคำตอบจากคนอื่น ๆ รวมถึง 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"
หากคุณต้องการใช้คีย์พจนานุกรมเป็นสตริงปกติคุณสามารถหลีกเลี่ยงสิ่งเหล่านั้นก่อนที่จะโทรหลาย ๆ แบบโดยใช้เช่นฟังก์ชันนี้:
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'