স্ট্রিংয়ের একাধিক সাবস্ট্রিংগুলি কীভাবে প্রতিস্থাপন করবেন?


284

আমি একাধিক স্ট্রিং প্রতিস্থাপন করতে .রেপস ফাংশনটি ব্যবহার করতে চাই।

আমি বর্তমানে আছে

string.replace("condition1", "")

তবে এর মতো কিছু করতে চাই

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

যদিও এটি ভাল সিনট্যাক্সের মতো মনে হয় না

এটি করার সঠিক উপায় কী? গ্রেপ / রেজেেক্সে আপনি কীভাবে করতে পারেন \1এবং \2ক্ষেত্রগুলিকে নির্দিষ্ট অনুসন্ধানের স্ট্রিংগুলিতে প্রতিস্থাপন করার মতো ধরণের


7
আপনি প্রদত্ত সমস্ত সমাধান চেষ্টা করেছেন? কোনটি দ্রুত?
tommy.carstensen

আমি বিভিন্ন পরিস্থিতিতে সমস্ত উত্তর পরীক্ষা করার জন্য সময় নিয়েছি। স্ট্যাকওভারফ্লো.com
পাবলো

1
সত্যি বলতে, আমি অন্য সকলের কাছে আপনার শৃঙ্খলিত পদ্ধতির পছন্দ করি। সমাধান খুঁজতে গিয়ে আমি এখানে পৌঁছেছি এবং আপনারটি ব্যবহার করেছি এবং এটি ঠিক কাজ করে।
ফ্রেমম্যান 1

@ ফ্রেমম্যান 1 +1। কেন এটি আরও আপগ্রেটেড হয় না কোনও চিহ্ন নেই। অন্যান্য সমস্ত পদ্ধতি কোড পড়া সহজতর করে তোলে। প্রতিস্থাপনের জন্য যদি কোনও ফাংশন পাস অ্যারে থাকে তবে এটি কাজ করবে। তবে আপনার শৃঙ্খলিত পদ্ধতিটি সবচেয়ে পরিষ্কার (কমপক্ষে স্থিতিশীল সংখ্যক প্রতিস্থাপনের সাথে)
আইসফায়ার

উত্তর:


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
প্রতিস্থাপনটি একক পাসে ঘটে।
অ্যান্ড্রু ক্লার্ক

26
ডিকেমিনস: এটি খুব চালাক নয়, এটি যতটা চালাক হওয়া উচিত তাও নয় ("|" এর সাথে যোগ দেওয়ার আগে আমাদের কীগুলি পুনরায়-পালাতে হবে)। ওভাররিঞ্জাইনার্ড কেন হয় না? কারণ এই ভাবে আমরা এটা এক পাস না (দ্রুত =), এবং আমরা একই সময়ে সব প্রতিস্থাপন করবেন, মত সংঘর্ষে এড়ানো "spamham sha".replace("spam", "eggs").replace("sha","md5")হচ্ছে "eggmd5m md5"পরিবর্তে"eggsham md5"
ভেড়া উড়ন্ত

8
@ অ্যান্ড্রু ক্লার্ক আমি ল্যাংড্ডা দিয়ে শেষ লাইনে কী ঘটছে তা যদি আপনি ব্যাখ্যা করতে পারতেন তবে আমি প্রশংসা করব।
খনিজগুলি

11
হাই, আমি এই স্নিপেটের পরিষ্কার সংস্করণ সহ একটি ছোট টুকরোটি তৈরি করেছি। এটি আরও কিছুটা দক্ষ হতে হবে: gist.github.com/bgusach/a967e0587d6e01e889fd1d776c5f3729
বিগুসাচ

15
অজগর 3 এর জন্য, iteritems () এর পরিবর্তে আইটেম () ব্যবহার করুন।
জঙ্গারি

127

আপনি কেবল একটি দুর্দান্ত ছোট লুপিং ফাংশন করতে পারেন।

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

textসম্পূর্ণ স্ট্রিংটি কোথায় এবং dicএকটি অভিধান - প্রতিটি সংজ্ঞাটি এমন একটি স্ট্রিং যা শব্দটির সাথে কোনও মিলকে প্রতিস্থাপন করবে।

দ্রষ্টব্য : পাইথন 3-এ, iteritems()প্রতিস্থাপন করা হয়েছেitems()


যত্নবান: পাইথন অভিধানগুলিতে পুনরাবৃত্তির জন্য নির্ভরযোগ্য অর্ডার নেই। এই সমাধানটি কেবল আপনার সমস্যা সমাধান করে যদি:

  • প্রতিস্থাপনের ক্রম অপ্রাসঙ্গিক
  • পূর্ববর্তী প্রতিস্থাপনের ফলাফলগুলি পরিবর্তন করার জন্য এটি প্রতিস্থাপনের জন্য ঠিক

এই ক্ষেত্রে:

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

"এটি আমার কুকুর এবং এটি আমার শূকর।"

একটি সম্ভাব্য সমাধান হ'ল অর্ডারডিক্ট ব্যবহার করা।

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
এটি স্ট্রিংকে পুনরাবৃত্তি করে তোলে দুবার ... পারফরম্যান্সের জন্য ভাল নয়।
ভ্যালেন্টিন লরেন্টজ

6
পারফরম্যান্স-ভিত্তিতে ভ্যালেন্টাইন যা বলে তার থেকেও খারাপ - ডিকের আইটেমগুলি যতবার আছে ততবার পাঠ্যটি অতিক্রম করবে! 'পাঠ্য' ছোট হলেও দুর্দান্ত পাঠ্যের জন্য ভয়ানক।
জেডোনার

3
এটি কিছু ক্ষেত্রে একটি ভাল সমাধান। উদাহরণস্বরূপ, আমি কেবল 2 টি অক্ষর উপস্থাপন করতে চাই এবং তারা যে ক্রমটিতে চলে সেটির বিষয়ে আমি যত্নশীল না কারণ প্রতিস্থাপন কীগুলি কোনও মানের সাথে মেলে না। তবে আমি কী চাইছে তা পরিষ্কার হওয়া চাই।
নাথান গারাবেদিয়ান

5
মনে রাখবেন এটি অপ্রত্যাশিত ফলাফল দিতে পারে কারণ প্রথম পুনরাবৃত্তিতে সদ্য সন্নিবেশ করা পাঠ্যটি দ্বিতীয় পুনরাবৃত্তির সাথে মেলাতে পারে। উদাহরণস্বরূপ, আমরা যদি নির্লিপ্তভাবে সমস্ত 'এ' কে 'বি' এবং সমস্ত 'বি' কে 'সি' দিয়ে প্রতিস্থাপন করার চেষ্টা করি, তবে 'বিসি' নয়, 'এবি' স্ট্রিংটি 'সিসি' তে রূপান্তরিত হবে।
আম্বোজ বিজ্জাক

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
এটি অত্যন্ত দরকারী, সহজ এবং পোর্টেবল।
ছিন্নাংশ

দেখতে সুন্দর লাগছে, তবে রেগেক্সের মতো প্রতিস্থাপন করা হয়নি: r ইন ((r '' s। ','। '), (R' \ s, ',', ')) এর জন্য:
মার্টিন

2
এটিকে 1-লাইনার তৈরি করতে: এস ইন = [s.replace (* আর) জন্য আর ইন (("বাদামী", "লাল"), ("অলস", "দ্রুত"))] [0]
কে কে

94

আপনি কার্যক্ষম হতে চান এমন ক্ষেত্রে হ্রাস ব্যবহার করে এখানে প্রথম সমাধানের একটি বৈকল্পিক is :)

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
করতে সহজ হবে replstuples একটি ক্রম এবং সঙ্গে দূরে না iteritems()কল। অর্থাত্ repls = ('hello', 'goodbye'), ('world', 'earth')এবং reduce(lambda a, kv: a.replace(*kv), repls, s)। এছাড়াও 3. পাইথন মধ্যে অপরিবর্তিত কাজ করবে
Martineau

চমৎকার! যদি আপনি পাইথন 3 ব্যবহার করে আইট্রেটেমের পরিবর্তে আইটেম ব্যবহার করেন (এখন ডিক্টস স্টাফগুলিতে সরানো হয়েছে)।
e.arbitrio

2
@ মার্টিনো: এটি সত্য নয় যে পাইথন 3 এ অপরিবর্তিত কাজ করে যেহেতু reduceঅপসারণ করা হয়েছে
নরম্যানিয়াস

5
@ নরম্যানিয়াস: reduceএখনও রয়েছে, যদিও এটি পাইথন 3- এ functoolsমডিউলের একটি অংশ ( ডক্স দেখুন ) তৈরি করা হয়েছিল, সুতরাং যখন আমি অপরিবর্তিত ছিলাম, আমি বোঝাতে চাইছিলাম একই কোডটি চালানো যেতে পারে - যদিও স্বীকার করা দরকার যে reduceএটি importপ্রয়োজন হলে সম্পাদনা করা হয়েছে যেহেতু এটি আর কোনও অন্তর্নির্মিত নয়।
মার্টিনো

35

এটি এফজে এবং মিনিকোয়ার্কের দুর্দান্ত উত্তরের মাত্র আরও সংক্ষিপ্ত পুনরুদ্ধার। একাধিক একযোগে স্ট্রিং প্রতিস্থাপনের জন্য আপনাকে যা করতে হবে তা হ'ল নিম্নলিখিত ফাংশন:

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
যদিও এটি একটি ভাল সমাধান, সমবর্তী স্ট্রিং প্রতিস্থাপনগুলি যথাযথভাবে তাদের যথাযথভাবে সম্পাদন করার মতো ফলাফল দেবে না (শৃঙ্খলিত করা) - যদিও তা বিবেচ্য নয়।
মার্টিনিউ

2
অবশ্যই, আপনার কোডের সাথে rep_dict = {"but": "mut", "mutton": "lamb"}স্ট্রিংয়ের "button"ফলাফল রয়েছে "mutton"তবে "lamb"প্রতিস্থাপনগুলি যদি একের পর এক জড়িত থাকে তবে তা দিবে ।
মার্টিনো

2
এটি এই কোডের মূল বৈশিষ্ট্য, কোনও ত্রুটি নয়। শৃঙ্খলিত প্রতিস্থাপনের সাথে এটি দুটি শব্দ একই সাথে প্রতিস্থাপনের এবং আমার উদাহরণের মতো পারস্পরিকভাবে পছন্দসই আচরণ অর্জন করতে পারেনি।
মিমজেজ

1
আপনার যদি এটির প্রয়োজন না হয় তবে এটি দুর্দান্ত বৈশিষ্ট্য বলে মনে হচ্ছে না। তবে এখানে আমরা একই সাথে প্রতিস্থাপনের কথা বলছি , তবে এটি প্রকৃতপক্ষে মূল বৈশিষ্ট্য। "চেইনযুক্ত" প্রতিস্থাপনের সাথে উদাহরণের আউটপুটটি হবে Do you prefer cafe? No, I prefer cafe.যা মোটেও কাম্য নয়।
মিমজে

@ ডেভিড আপনার নিজের উত্তর লিখুন, আপনার সম্পাদনাটি খুব মৌলিক
উমনিওব

29

আমি এফজেগুলিকে চমৎকার উত্তরটির উপর এটি তৈরি করেছি:

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é.

মনে রাখবেন যেহেতু প্রতিস্থাপনটি কেবল একটি পাসে করা হয়, তাই "ক্যাফে" "চা" তে পরিবর্তিত হয় তবে এটি "ক্যাফে" -র পরিবর্তিত হয় না।

যদি আপনার একই প্রতিস্থাপনটি অনেক বার করার দরকার হয় তবে আপনি সহজেই প্রতিস্থাপনের কাজটি তৈরি করতে পারেন:

>>> 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
আমার মতো অজগর নুবসের জন্য কেউ কি এই ধাপে ধাপে ব্যাখ্যা করতে পারেন?
জুলিয়ান সুয়ারেজ

সহকর্মী অজগর এখানে নবুব, সুতরাং আমি এটি বুঝতে একটি অসম্পূর্ণ শট নিতে যাচ্ছি .. ক। স্টাফ-টু রিপ্লেসে কী_ভ্যালুগুলি ভেঙে ফেলা (কীগুলি "|" এর সাথে যুক্ত হয়েছে) এবং যুক্তি (যদি ম্যাচটি কী হয় তবে প্রত্যাবর্তনের মান) বি। একটি রেজেক্স পার্সার তৈরি করুন ("প্যাটার্ন" যা কীগুলি সন্ধান করে এবং প্রদত্ত যুক্তি ব্যবহার করে) - এটিকে একটি ল্যাম্বডা ফাংশনে আবদ্ধ করুন এবং ফিরে আসুন। স্টাফ আমি এখন সন্ধান করছি: রি.এম, এবং প্রতিস্থাপন যুক্তির জন্য ল্যাম্বদার প্রয়োজনীয়তা।
শিয়াল

1
@ ফক্স আপনি এটি পেয়েছেন আপনি ল্যাম্বডা ব্যবহার না করে কোনও ফাংশন সংজ্ঞায়িত করতে পারেন, কোডটি ছোট করার জন্য এটি কেবল। তবে নোট করুন যে pattern.subকেবলমাত্র একটি প্যারামিটার (প্রতিস্থাপনের জন্য পাঠ্য) সহ কোনও ফাংশন প্রত্যাশা করে, সুতরাং ফাংশনটিতে অ্যাক্সেস থাকা দরকার replace_dictমাল্টলাইনre.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একটি ব্যতিক্রম বাড়ে, তাই ব্যবহারকারীদের কাছ থেকে টেমপ্লেটগুলি নেওয়ার সময় সাবধান হন।
বার্ট ফ্রেডারিচস

2
এই পদ্ধতির একটি অপূর্ণতা হ'ল টেমপ্লেটটিতে অবশ্যই সমস্ত কিছু থাকতে হবে এবং তার চেয়ে বেশি কিছু নয় $ স্ট্রিংগুলি প্রতিস্থাপন করতে হবে, এখানে দেখুন
রোল্ফবলি

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তবে একটি অদ্ভুত আচরণ পাবেন।
বিগুসাচ

1
যদি অর্ডারটি তাত্পর্যপূর্ণ হয় তবে উপরের ডিকের পরিবর্তে আপনি একটি অ্যারে ব্যবহার করতে পারেন: b = [ ['i', 'Z'], ['s', 'Y'] ]; for x,y in (b): a = a.replace(x, y) তারপরে আপনি যদি আপনার অ্যারে জোড়া অর্ডার করতে সচেতন হন তবে আপনি নিশ্চিত করতে পারেন যে আপনি পুনরাবৃত্তভাবে প্রতিস্থাপন করবেন না।
কোড-রিড

দেখে মনে হচ্ছে পাইথনগুলি এখন পাইথন ৩.7.০ থেকে অর্ডার বজায় রেখেছে । আমি এটি পরীক্ষা করেছি এবং এটি সর্বশেষ স্থিতিশীল পাইথন 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 নেই।
পাবলো

আমি কেন একটি তালিকায় আউটপুট পাব?
জনরাও 07

1
@ জনরাও07 ঠিক আছে একটি তালিকা বোঝার একটি তালিকা তৈরি করে। এজন্যই, এই ক্ষেত্রে, আপনি পাবেন ['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। এটি অ্যান্ড্রু ক্লার্কের উত্তরের উপর ভিত্তি করে তৈরি হয়েছে, যা কিছুটা পরিষ্কার হয়ে গেছে, এবং এটি ক্ষেত্রেও আচ্ছাদিত হয় যখন স্ট্রিং প্রতিস্থাপনের জন্য অন্য স্ট্রিংয়ের একটি স্ট্রিং থাকে (দীর্ঘতর স্ট্রিং জেতা হয়)

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
পরিবর্তে এটি গ্রহণযোগ্য উত্তর হওয়া উচিত ছিল কারণ রেজেক্সটি সমস্ত কী থেকে দৈর্ঘ্যের ক্রমবর্ধমান ক্রমে বাছাই করে এবং তাদের সাথে যোগ দিয়ে | রেজেক্স অল্টারনেশন অপারেটর। এবং বাছাই করা প্রয়োজনীয় যাতে কোনও বিকল্প থাকে যদি সমস্ত সম্ভাব্য পছন্দগুলির মধ্যে দীর্ঘতম নির্বাচন করা হয়।
শচীন এস

আমি সম্মত হই যে এটি বাছাই করার জন্য ধন্যবাদ, এটি সেরা সমাধান। বাছাই করা ছাড়াও আমার মূল উত্তরটির অনুরূপ, তাই আমি আমার সমাধানের জন্যও বাছাই ধার নিয়েছি, যাতে নিশ্চিত হয়ে যায় যে এইরকম গুরুত্বপূর্ণ বৈশিষ্ট্যটি কেউ মিস করবে না।
মিমজেঞ্জ

6

আমার এমন একটি সমাধানের দরকার ছিল যেখানে স্ট্রিংগুলি প্রতিস্থাপন করা নিয়মিত প্রকাশ হতে পারে, উদাহরণস্বরূপ, একাধিক শ্বেত স্পেস অক্ষরকে একক দিয়ে প্রতিস্থাপন করে দীর্ঘ পাঠকে সাধারণকরণে সহায়তা করা। 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"

নীচের ফাংশনটি আপনার অভিধান কীগুলির মধ্যে ভুল নিয়মিত প্রকাশ খুঁজে পেতে সহায়তা করতে পারে (যেহেতু একাধিক_স্থান থেকে ত্রুটি বার্তাটি খুব একটা বলছে না):

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

উপরে আমার প্রশ্নের উত্তর stackoverflow.com/questions/45630940/...
cmarqu

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(আমার পরীক্ষার শর্তে)।

আপনার একেবারে ফ্ল্যাশটেক্সট লাইব্রেরি ব্যবহার করার চেষ্টা করা উচিত ( এখানে ব্লগ পোস্ট , গিথুব এখানে )। আমার ক্ষেত্রে এটি 1.8 এস থেকে 0.015 এস (নিয়মিত এক্সপ্রেশন 7..7 সেকেন্ডে নিয়েছে) দ্রুততর দুটি আদেশের চেয়ে কিছুটা কম ছিল প্রতিটি ডকুমেন্টের জন্য ।

উপরের লিঙ্কগুলিতে ব্যবহারের উদাহরণগুলি পাওয়া সহজ তবে এটি একটি কার্যকরী উদাহরণ:

    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 এছাড়াও পুরো শব্দ জন্য দেখায় (তাই মেলে না হবে 'ম' হল ' হয় ')। আপনার লক্ষ্যটি বেশ কয়েকটি শব্দ হলে ('হ্যালো' দ্বারা 'এটি হ'ল' প্রতিস্থাপন করে) এটি দুর্দান্ত কাজ করে।


আপনার যদি এইচটিএমএল ট্যাগগুলি প্রতিস্থাপন করতে হয় তবে এটি কীভাবে কাজ করবে? যেমন প্রতিস্থাপন <p>সঙ্গে /n। আমি আপনার পদ্ধতির চেষ্টা করেছি কিন্তু ট্যাগগুলির সাথে ফ্ল্যাশটেক্সট এটি বিশ্লেষণ করছে না?
ওরফে51

1
আপনি নিশ্চিত হিসাবে এটি কেন কাজ করছে না তা আমি নিশ্চিত নই। একটি সম্ভাবনা হ'ল এই ট্যাগগুলি স্পেস দ্বারা পৃথক করা হয়নি, এবং মনে রাখবেন ফ্ল্যাশটেক্সট পুরো শব্দটির সন্ধান করে। এর চারপাশের উপায় হ'ল প্রথমে একটি সাধারণ প্রতিস্থাপন ব্যবহার করা, যাতে "হাই <পি> সেখানে" "হাই <পি> সেখানে" পরিণত হয়। আপনার কাজ শেষ হওয়ার পরে অযাচিত স্থানগুলি সরানোর জন্য আপনাকে সতর্কতা অবলম্বন করা প্রয়োজন (এছাড়াও সরল প্রতিস্থাপন?) আশা করি এইটি কাজ করবে.
পাবলো

ধন্যবাদ, আপনি কি কোনও শব্দের সমাপ্তি চিহ্নিত করতে <এবং >চিহ্নিত করতে পারেন (তবে প্রতিস্থাপনে অন্তর্ভুক্ত করবেন)?
ওরফে 5১

1
আমি বিশ্বাস করি যে "শব্দ" কেবল স্থান দ্বারা চিহ্নিত করা হয়েছে are সম্ভবত কিছু optionচ্ছিক প্যারামিটার রয়েছে যা আপনি "কীওয়ার্ডপ্রসেসর" এ সেট করতে পারেন। অন্যথায় উপরের পদ্ধতির বিষয়টি বিবেচনা করুন: "<" দ্বারা "<" দ্বারা বিকল্প পরিবর্তন করুন, ফ্ল্যাশটেক্সট প্রয়োগ করুন এবং তারপরে বিকল্পটি ফিরে করুন (আপনার ক্ষেত্রে উদাহরণস্বরূপ, "<" "<" থেকে "\ 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'

মন্তব্য:

  • এটি ইনপুট অভিধান গ্রহণ করে।
  • পাইথন ডিক্টস 3.6 হিসাবে কী অর্ডার সংরক্ষণ করে; অন্যান্য উত্তরের সাথে সম্পর্কিত সাবধানতা আর প্রাসঙ্গিক নয়। পিছনের সামঞ্জস্যের জন্য কেউ একটি টিউপল-ভিত্তিক সংস্করণটি অবলম্বন করতে পারে:
>>> mrep = lambda s, d: s if not d else mrep(s.replace(*d.pop()), d)
>>> mrep('abcabc', [('a', '1'), ('c', '2')])

দ্রষ্টব্য: পাইথনের সমস্ত পুনরাবৃত্ত ক্রিয়াকলাপগুলির মতো, খুব বড় পুনরাবৃত্তির গভীরতা (যেমন খুব বড় প্রতিস্থাপন অভিধান) এর ফলে ত্রুটি ঘটবে। যেমন এখানে দেখুন ।


আমি একটি বড় অভিধান ব্যবহার করার সময় পুনরাবৃত্তির ত্রুটিতে চলেছি!
পাবলো

@ পাবলো আকর্ষণীয়। কত বড়? নোট করুন যে এটি সমস্ত পুনরাবৃত্ত ফাংশনগুলির জন্য ঘটে। : এখানে উদাহরণস্বরূপ দেখুন stackoverflow.com/questions/3323001/...
mcsoini

বদল আমার অভিধান ... 100 কিলোবাইট পদ পাসে এতদূর string.replace ব্যবহার করছে পর্যন্ত সেরা পদ্ধতির।
পাবলো

1
@ পাবলো সেক্ষেত্রে আপনি পুনরাবৃত্ত ফাংশন ব্যবহার করতে পারবেন না। সাধারণভাবে,sys.getrecursionlimit() বেশ কয়েক হাজার, সর্বোচ্চ। একটি লুপ বা এর মতো কিছু ব্যবহার করুন বা বিকল্পগুলি সরল করার চেষ্টা করুন।
mcsoini

হ্যাঁ, আমি আশঙ্কা করছি এখানে আসলে কোনও শর্টকাট নেই।
পাবলো

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

আপনি 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

শুধুমাত্র একটি অক্ষর প্রতিস্থাপনের জন্য 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

অ্যান্ড্রুয়ের মূল্যবান উত্তর থেকে শুরু করে আমি একটি স্ক্রিপ্ট তৈরি করেছি যা একটি ফাইল থেকে অভিধান লোড করে এবং প্রতিস্থাপনগুলি করতে খোলা ফোল্ডারের সমস্ত ফাইলকে বিশদভাবে জানায়। স্ক্রিপ্টটি বাহ্যিক ফাইল থেকে ম্যাপিং লোড করে যাতে আপনি বিভাজক সেট করতে পারেন। আমি একটি শিক্ষানবিশ কিন্তু একাধিক ফাইলে একাধিক বিকল্পগুলি করার সময় আমি এই স্ক্রিপ্টটি খুব দরকারী বলে মনে করেছি। এটি সেকেন্ডে 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)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.