0

I use the search functionre.finditer() and get span as 1 tuple

I'm trying a function that can handle any input

import re
text = "Thanks for the help, your Help is really good, it's really a big help"

def replace(text,key,value,NumberL):
    matches = list(re.finditer(key,text,re.I))
    for i in NumberL:
        newT = matches[i-1]
        text = text[:newT.start(0)] + value + text[newT.end(0):]
    print(text)
replace(text,'help','job',[2,3])
>>> #Thanks for the help, your job is really good, it's really a big hjob

output will be wrong starting from 2nd word is changed

Tmag
  • 33
  • 5

1 Answers1

0

Using re.sub would be easier than re.finditer:

import re
text = "Thanks for the help, your Help is really good, it's really a big help"
text = re.sub('help', 'job', text, flags=re.I)
print(text)
# => Thanks for the job, your job is really good, it's really a big job

If you really need to use re.finditer, then you need to cut-and-paste the string yourself. You also want to reverse the matches, because the indices for later matches will get messed up with earlier edits ("cutting the branch you are sitting on").

import re
text = "Thanks for the help, your Help is really good, it's really a big help"
for match in reversed(list(re.finditer('help', text, re.I))):
    text = text[:match.start(0)] + "job" + text[match.end(0):]
print(text)
# => Thanks for the job, your job is really good, it's really a big job

To only switch the items you want, you either make a more precise regex, or find a different criterion to do so. For example, to only replace the second one, which is capitalised, you could search for "Help" instead of "help", and not specify the re.I flag. Or you could search for (?<=help.*)help with re.I (a "help" that is preceded by another "help"). Or you could use re.sub with a replacer function and a nonlocal counter, so that you only replace the second match. Or you could use re.finditer to find a list of matches, extract the second one, and then perform the cut-and-paste from the first example.


'extract the second one' this is exactly my problem. How can i extract it from group of finditer?

import re
text = "Thanks for the help, your Help is really good, it's really a big help"
matches = list(re.finditer('help', text, re.I))
second_match = matches[1]
text = text[:second_match.start(0)] + "job" + text[second_match.end(0):]
print(text)
# => Thanks for the help, your job is really good, it's really a big help
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Thanks For help. this is just a small example, actually i need to find words that appear in a certain text and replace the specified words with other words. – Tmag Jun 17 '22 at 01:54
  • 'extract the second one' this is exactly my problem. How can i extract it from group of finditer? – Tmag Jun 17 '22 at 02:01
  • can you help me with the above supplement? – Tmag Jun 17 '22 at 02:51
  • "can't seem to get it to work" is not a useful problem statement. What about it does not work? What does it do that you don't want, or what does it not do that you do want? Is there an error? What is it? Also, if I understand what you want to do, you just need to replace `matches[1]` with `matches[NumberL]` in my last snippet, no need for a loop. – Amadan Jun 17 '22 at 02:59
  • sorry for my stupidity. i misunderstood NumberL what i want is to match word's ordinal number as [1,2,3] not [0,1,2] – Tmag Jun 17 '22 at 03:18
  • `matches[NumberL - 1]`? – Amadan Jun 17 '22 at 03:19
  • this way can only replace the first word and all the following words are wrong! – Tmag Jun 17 '22 at 04:25