أود استخدام دالة .replace لاستبدال عدة سلاسل نصية.
لدي حالياً
string.replace("condition1", "")لكن أود أن يكون لدي شيء مثل
string.replace("condition1", "").replace("condition2", "text")على الرغم من أن ذلك لا يبدو مثل بناء جملة جيد
ما هي الطريقة الصحيحة للقيام بذلك؟ مشابهة للطريقة التي يمكنك بها في grep/regex استخدام \1 و \2 لاستبدال الحقول بسلاسل البحث معينة
الإجابة رقم 1إليك مثال قصير يجب أن ينجز المهمة مع التعبيرات النمطية:
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.items()) 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--' الإجابة رقم 2يمكنك فقط إنشاء دالة صغيرة جميلة تعمل بشكل متكرر.
def replace_all(text, dic): for i, j in dic.iteritems(): text = text.replace(i, j) return textحيث أن text هو السلسلة الكاملة و dic هو قاموس — كل تعريف هو سلسلة ستستبدل المطابقة للمصطلح.
ملاحظة: في بايثون 3، تم استبدال iteritems() بـ items()
تنبيه: القواميس في بايثون لا تمتلك ترتيبًا موثوقًا به للتكرار. هذا الحل يحل مشكلتك فقط إذا:
ترتيب الاستبدالات غير مهملا بأس في أن يؤدي الاستبدال إلى تغيير نتائج الاستبدالات السابقةتحديث: البيان أعلاه المتعلق بترتيب الإدراج لا ينطبق على إصدارات بايثون الأكبر من أو تساوي 3.6، حيث تم تغيير القواميس القياسية لاستخدام ترتيب الإدراج أثناء التكرار.
على سبيل المثال:
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:
"This is my pig and this is my pig."المخرج المحتمل #2
"This is my dog and this is my pig."إحدى الحلول الممكنة هي استخدام 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 كبيرة جدًا أو إذا كانت هناك العديد من الأزواج في القاموس.
الإجابة رقم 3لماذا لا يكون هناك حل واحد مثل هذا؟
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 الإجابة رقم 4إليك نسخة من الحل الأول باستخدام reduce (استيراد من functools)، في حال كنت تحب الأسلوب الوظيفي. :)
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) الإجابة رقم 5هذا مجرد ملخص أكثر إيجازًا لإجابات F.J و MiniQuark الرائعة وأخيرًا التحسين الحاسم من bgusach. كل ما تحتاجه لتحقيق استبدالات متعددة للسلاسل في نفس الوقت هو الدالة التالية:
import re 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.'إذا رغبت، يمكنك إنشاء دوال استبدال مخصصة خاصة بك بدءًا من هذه الدالة الأبسط.
الإجابة رقم 6بدءًا من 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' الإجابة رقم 7بنيت هذا اعتمادًا على إجابة F.J الممتازة:
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é.لاحظ أنه نظرًا لأن الاستبدال يتم في تمريرة واحدة فقط، فإن "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!\"تحسينات:
حوَّل الكود إلى دالةتمت إضافة دعم متعدد الأسطرتم إصلاح خطأ في الهروبمن السهل إنشاء دالة لاستبدال عدة عناصر محددةاستمتع! :-)
الإجابة رقم 8أود أن أقترح استخدام قوالب السلاسل. فقط ضع السلسلة المراد استبدالها في قاموس وكل شيء جاهز! مثال من 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' الإجابة رقم 9هذه وجهة نظري بقيمة 0.02 دولار. وهي مستندة على إجابة أندرو كلارك، لكنها أوضح قليلاً، وتشمل أيضاً الحالة التي يكون فيها النص المراد استبداله جزءًا من نص آخر يجب استبداله (النص الأطول هو الذي يُستبدل).
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)إنه موجود في هذا الملخص، لا تتردد في تعديله إذا كان لديك أي اقتراح.
الإجابة رقم 10في حالتي، كنت بحاجة إلى استبدال بسيط للمفاتيح الفريدة بالأسماء، لذا خطرت لي هذه الفكرة:
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.'