Tôi cần một giải pháp trong đó các chuỗi được thay thế có thể là một biểu thức thông thường, ví dụ để giúp bình thường hóa một văn bản dài bằng cách thay thế nhiều ký tự khoảng trắng bằng một ký tự. Dựa trên một chuỗi câu trả lời từ những người khác, bao gồm MiniQuark và mmj, đây là những gì tôi nghĩ ra:
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)
Nó hoạt động cho các ví dụ được đưa ra trong các câu trả lời khác, ví dụ:
>>> 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.'
Điều chính đối với tôi là bạn cũng có thể sử dụng các biểu thức thông thường, ví dụ để chỉ thay thế toàn bộ các từ hoặc để bình thường hóa khoảng trắng:
>>> 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"
Nếu bạn muốn sử dụng các khóa từ điển như các chuỗi bình thường, bạn có thể thoát các khóa đó trước khi gọi nhiều numplace bằng cách sử dụng chức năng này:
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"
Hàm sau có thể giúp tìm các biểu thức chính quy sai trong số các khóa từ điển của bạn (vì thông báo lỗi từ nhiều bit không phải là rất hay):
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())
Lưu ý rằng nó không xâu chuỗi các thay thế, thay vào đó thực hiện chúng đồng thời. Điều này làm cho nó hiệu quả hơn mà không hạn chế những gì nó có thể làm. Để bắt chước hiệu ứng của chuỗi, bạn có thể chỉ cần thêm nhiều cặp thay thế chuỗi và đảm bảo thứ tự dự kiến của các cặp:
>>> multiple_replace("button", {"but": "mut", "mutton": "lamb"})
'mutton'
>>> multiple_replace("button", [("button", "lamb"),
... ("but", "mut"), ("mutton", "lamb")])
'lamb'