Replace all occurrences in string but the first one
up vote
2
down vote
favorite
Given the string:
X did something. X found it to be good, and so X went home.
I would like to replace all occurrences of X
but the first one, with Y, such that the output string would look like:
X did something. Y found it to be good, and so Y went home.
I tried many regex patterns (based on https://vi.stackexchange.com/questions/10905/substitution-how-to-ignore-the-nth-first-occurrences-of-a-pattern) but failed to implement this with Python
python regex
add a comment |
up vote
2
down vote
favorite
Given the string:
X did something. X found it to be good, and so X went home.
I would like to replace all occurrences of X
but the first one, with Y, such that the output string would look like:
X did something. Y found it to be good, and so Y went home.
I tried many regex patterns (based on https://vi.stackexchange.com/questions/10905/substitution-how-to-ignore-the-nth-first-occurrences-of-a-pattern) but failed to implement this with Python
python regex
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Given the string:
X did something. X found it to be good, and so X went home.
I would like to replace all occurrences of X
but the first one, with Y, such that the output string would look like:
X did something. Y found it to be good, and so Y went home.
I tried many regex patterns (based on https://vi.stackexchange.com/questions/10905/substitution-how-to-ignore-the-nth-first-occurrences-of-a-pattern) but failed to implement this with Python
python regex
Given the string:
X did something. X found it to be good, and so X went home.
I would like to replace all occurrences of X
but the first one, with Y, such that the output string would look like:
X did something. Y found it to be good, and so Y went home.
I tried many regex patterns (based on https://vi.stackexchange.com/questions/10905/substitution-how-to-ignore-the-nth-first-occurrences-of-a-pattern) but failed to implement this with Python
python regex
python regex
edited Nov 10 at 14:54
petezurich
3,30381631
3,30381631
asked Nov 10 at 14:29
Amit
1,22711132
1,22711132
add a comment |
add a comment |
6 Answers
6
active
oldest
votes
up vote
6
down vote
accepted
str.partition
splits a string into the part before a delimiter, the delimiter itself, and the part after, or the string and two empty strings if the delimiter doesn’t exist. What that comes down to is:
s = 'X did something. X found it to be good, and so X went home.'
before, first, after = s.partition('X')
result = before + first + after.replace('X', 'Y')
add a comment |
up vote
5
down vote
You cold use the fact that re.sub uses a function:
import re
def repl(match, count=[0]):
x, = count
count[0] += 1
if x > 0:
return 'Y'
return 'X'
print(re.sub('X', repl, 'X did something. X found it to be good, and so X went home.'))
Output
X did something. Y found it to be good, and so Y went home.
The idea is to use a function that keeps the count of seen X
and then replace it when the count if above 1.
add a comment |
up vote
2
down vote
Another Option is to find the first one and only after replace all X
occurrences.
Finally, concat the beginning to the start of the sentence
st = 'X did something. X found it to be good, and so X went home.'
first_found = st.find('X')
print (st[:first_found + 1] + st[first_found + 1:].replace('X', 'Y'))
# X did something. Y found it to be good, and so Y went home.
add a comment |
up vote
2
down vote
Here's a low tech solution without regex. :)
>>> s = 'X did something. X found it to be good, and so X went home'
>>> s = s.replace('X', 'Y').replace('Y', 'X', 1)
>>> s
>>> 'X did something. Y found it to be good, and so Y went home'
Solution if 'Y'
can exist in the original string:
def replace_tail(s, target, replacement):
try:
pos = s.index(target)
except ValueError:
return s
pos += len(target)
head = s[:pos]
tail = s[pos:]
return head + tail.replace(target, replacement)
Demo:
>>> s = 'Today YYY and XXX did something. XXX found it to be good, and so XXX went home without YYY.'
>>> replace_tail(s, 'XXX', 'YYY')
>>> 'Today YYY and XXX did something. YYY found it to be good, and so YYY went home without YYY.'
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
add a comment |
up vote
1
down vote
Apply iteratively the regex after finding the first match over the remaining of the string. Or just using replace
if it is possible.
add a comment |
up vote
1
down vote
We can use slicing to produce two string: first one up to (and including) the first element, and the next slice that contains the rest. We can then apply the replace part on that part, and merge these back:
def replace_but_first(text, search, replace):
try:
idx = text.index(search) + len(search)
return text[:idx] + text[idx:].replace(search, replace)
except ValueError: # we did not found a single match
return text
For example:
>>> replace_but_first('X did something. X found it to be good, and so X went home.', 'X', 'Y')
'X did something. Y found it to be good, and so Y went home.'
@Ry-: sorry I was confused betweenindex
andfind
.
– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.
– Willem Van Onsem
Nov 10 at 14:41
add a comment |
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
accepted
str.partition
splits a string into the part before a delimiter, the delimiter itself, and the part after, or the string and two empty strings if the delimiter doesn’t exist. What that comes down to is:
s = 'X did something. X found it to be good, and so X went home.'
before, first, after = s.partition('X')
result = before + first + after.replace('X', 'Y')
add a comment |
up vote
6
down vote
accepted
str.partition
splits a string into the part before a delimiter, the delimiter itself, and the part after, or the string and two empty strings if the delimiter doesn’t exist. What that comes down to is:
s = 'X did something. X found it to be good, and so X went home.'
before, first, after = s.partition('X')
result = before + first + after.replace('X', 'Y')
add a comment |
up vote
6
down vote
accepted
up vote
6
down vote
accepted
str.partition
splits a string into the part before a delimiter, the delimiter itself, and the part after, or the string and two empty strings if the delimiter doesn’t exist. What that comes down to is:
s = 'X did something. X found it to be good, and so X went home.'
before, first, after = s.partition('X')
result = before + first + after.replace('X', 'Y')
str.partition
splits a string into the part before a delimiter, the delimiter itself, and the part after, or the string and two empty strings if the delimiter doesn’t exist. What that comes down to is:
s = 'X did something. X found it to be good, and so X went home.'
before, first, after = s.partition('X')
result = before + first + after.replace('X', 'Y')
answered Nov 10 at 14:36
Ry-♦
165k36334355
165k36334355
add a comment |
add a comment |
up vote
5
down vote
You cold use the fact that re.sub uses a function:
import re
def repl(match, count=[0]):
x, = count
count[0] += 1
if x > 0:
return 'Y'
return 'X'
print(re.sub('X', repl, 'X did something. X found it to be good, and so X went home.'))
Output
X did something. Y found it to be good, and so Y went home.
The idea is to use a function that keeps the count of seen X
and then replace it when the count if above 1.
add a comment |
up vote
5
down vote
You cold use the fact that re.sub uses a function:
import re
def repl(match, count=[0]):
x, = count
count[0] += 1
if x > 0:
return 'Y'
return 'X'
print(re.sub('X', repl, 'X did something. X found it to be good, and so X went home.'))
Output
X did something. Y found it to be good, and so Y went home.
The idea is to use a function that keeps the count of seen X
and then replace it when the count if above 1.
add a comment |
up vote
5
down vote
up vote
5
down vote
You cold use the fact that re.sub uses a function:
import re
def repl(match, count=[0]):
x, = count
count[0] += 1
if x > 0:
return 'Y'
return 'X'
print(re.sub('X', repl, 'X did something. X found it to be good, and so X went home.'))
Output
X did something. Y found it to be good, and so Y went home.
The idea is to use a function that keeps the count of seen X
and then replace it when the count if above 1.
You cold use the fact that re.sub uses a function:
import re
def repl(match, count=[0]):
x, = count
count[0] += 1
if x > 0:
return 'Y'
return 'X'
print(re.sub('X', repl, 'X did something. X found it to be good, and so X went home.'))
Output
X did something. Y found it to be good, and so Y went home.
The idea is to use a function that keeps the count of seen X
and then replace it when the count if above 1.
answered Nov 10 at 14:35
Daniel Mesejo
7,8541921
7,8541921
add a comment |
add a comment |
up vote
2
down vote
Another Option is to find the first one and only after replace all X
occurrences.
Finally, concat the beginning to the start of the sentence
st = 'X did something. X found it to be good, and so X went home.'
first_found = st.find('X')
print (st[:first_found + 1] + st[first_found + 1:].replace('X', 'Y'))
# X did something. Y found it to be good, and so Y went home.
add a comment |
up vote
2
down vote
Another Option is to find the first one and only after replace all X
occurrences.
Finally, concat the beginning to the start of the sentence
st = 'X did something. X found it to be good, and so X went home.'
first_found = st.find('X')
print (st[:first_found + 1] + st[first_found + 1:].replace('X', 'Y'))
# X did something. Y found it to be good, and so Y went home.
add a comment |
up vote
2
down vote
up vote
2
down vote
Another Option is to find the first one and only after replace all X
occurrences.
Finally, concat the beginning to the start of the sentence
st = 'X did something. X found it to be good, and so X went home.'
first_found = st.find('X')
print (st[:first_found + 1] + st[first_found + 1:].replace('X', 'Y'))
# X did something. Y found it to be good, and so Y went home.
Another Option is to find the first one and only after replace all X
occurrences.
Finally, concat the beginning to the start of the sentence
st = 'X did something. X found it to be good, and so X went home.'
first_found = st.find('X')
print (st[:first_found + 1] + st[first_found + 1:].replace('X', 'Y'))
# X did something. Y found it to be good, and so Y went home.
answered Nov 10 at 14:39
omri_saadon
6,65531444
6,65531444
add a comment |
add a comment |
up vote
2
down vote
Here's a low tech solution without regex. :)
>>> s = 'X did something. X found it to be good, and so X went home'
>>> s = s.replace('X', 'Y').replace('Y', 'X', 1)
>>> s
>>> 'X did something. Y found it to be good, and so Y went home'
Solution if 'Y'
can exist in the original string:
def replace_tail(s, target, replacement):
try:
pos = s.index(target)
except ValueError:
return s
pos += len(target)
head = s[:pos]
tail = s[pos:]
return head + tail.replace(target, replacement)
Demo:
>>> s = 'Today YYY and XXX did something. XXX found it to be good, and so XXX went home without YYY.'
>>> replace_tail(s, 'XXX', 'YYY')
>>> 'Today YYY and XXX did something. YYY found it to be good, and so YYY went home without YYY.'
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
add a comment |
up vote
2
down vote
Here's a low tech solution without regex. :)
>>> s = 'X did something. X found it to be good, and so X went home'
>>> s = s.replace('X', 'Y').replace('Y', 'X', 1)
>>> s
>>> 'X did something. Y found it to be good, and so Y went home'
Solution if 'Y'
can exist in the original string:
def replace_tail(s, target, replacement):
try:
pos = s.index(target)
except ValueError:
return s
pos += len(target)
head = s[:pos]
tail = s[pos:]
return head + tail.replace(target, replacement)
Demo:
>>> s = 'Today YYY and XXX did something. XXX found it to be good, and so XXX went home without YYY.'
>>> replace_tail(s, 'XXX', 'YYY')
>>> 'Today YYY and XXX did something. YYY found it to be good, and so YYY went home without YYY.'
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
add a comment |
up vote
2
down vote
up vote
2
down vote
Here's a low tech solution without regex. :)
>>> s = 'X did something. X found it to be good, and so X went home'
>>> s = s.replace('X', 'Y').replace('Y', 'X', 1)
>>> s
>>> 'X did something. Y found it to be good, and so Y went home'
Solution if 'Y'
can exist in the original string:
def replace_tail(s, target, replacement):
try:
pos = s.index(target)
except ValueError:
return s
pos += len(target)
head = s[:pos]
tail = s[pos:]
return head + tail.replace(target, replacement)
Demo:
>>> s = 'Today YYY and XXX did something. XXX found it to be good, and so XXX went home without YYY.'
>>> replace_tail(s, 'XXX', 'YYY')
>>> 'Today YYY and XXX did something. YYY found it to be good, and so YYY went home without YYY.'
Here's a low tech solution without regex. :)
>>> s = 'X did something. X found it to be good, and so X went home'
>>> s = s.replace('X', 'Y').replace('Y', 'X', 1)
>>> s
>>> 'X did something. Y found it to be good, and so Y went home'
Solution if 'Y'
can exist in the original string:
def replace_tail(s, target, replacement):
try:
pos = s.index(target)
except ValueError:
return s
pos += len(target)
head = s[:pos]
tail = s[pos:]
return head + tail.replace(target, replacement)
Demo:
>>> s = 'Today YYY and XXX did something. XXX found it to be good, and so XXX went home without YYY.'
>>> replace_tail(s, 'XXX', 'YYY')
>>> 'Today YYY and XXX did something. YYY found it to be good, and so YYY went home without YYY.'
edited Nov 10 at 14:42
answered Nov 10 at 14:32
timgeb
43.3k106084
43.3k106084
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
add a comment |
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
2
2
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
Gonna run in to trouble if a Y already existed before the X.
– Ry-♦
Nov 10 at 14:33
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
@Ry- correct! Amit, can you clarify if this can happen? I might have to increase the tech level a bit.
– timgeb
Nov 10 at 14:35
1
1
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
Nice catch, In my use case, this can never happen. I like all of the proposed solutions, but this one is most elegant.
– Amit
Nov 10 at 14:38
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
@Amit in any case, I added a function that works in both scenarios.
– timgeb
Nov 10 at 14:47
add a comment |
up vote
1
down vote
Apply iteratively the regex after finding the first match over the remaining of the string. Or just using replace
if it is possible.
add a comment |
up vote
1
down vote
Apply iteratively the regex after finding the first match over the remaining of the string. Or just using replace
if it is possible.
add a comment |
up vote
1
down vote
up vote
1
down vote
Apply iteratively the regex after finding the first match over the remaining of the string. Or just using replace
if it is possible.
Apply iteratively the regex after finding the first match over the remaining of the string. Or just using replace
if it is possible.
answered Nov 10 at 14:32
OmG
7,28252643
7,28252643
add a comment |
add a comment |
up vote
1
down vote
We can use slicing to produce two string: first one up to (and including) the first element, and the next slice that contains the rest. We can then apply the replace part on that part, and merge these back:
def replace_but_first(text, search, replace):
try:
idx = text.index(search) + len(search)
return text[:idx] + text[idx:].replace(search, replace)
except ValueError: # we did not found a single match
return text
For example:
>>> replace_but_first('X did something. X found it to be good, and so X went home.', 'X', 'Y')
'X did something. Y found it to be good, and so Y went home.'
@Ry-: sorry I was confused betweenindex
andfind
.
– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.
– Willem Van Onsem
Nov 10 at 14:41
add a comment |
up vote
1
down vote
We can use slicing to produce two string: first one up to (and including) the first element, and the next slice that contains the rest. We can then apply the replace part on that part, and merge these back:
def replace_but_first(text, search, replace):
try:
idx = text.index(search) + len(search)
return text[:idx] + text[idx:].replace(search, replace)
except ValueError: # we did not found a single match
return text
For example:
>>> replace_but_first('X did something. X found it to be good, and so X went home.', 'X', 'Y')
'X did something. Y found it to be good, and so Y went home.'
@Ry-: sorry I was confused betweenindex
andfind
.
– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.
– Willem Van Onsem
Nov 10 at 14:41
add a comment |
up vote
1
down vote
up vote
1
down vote
We can use slicing to produce two string: first one up to (and including) the first element, and the next slice that contains the rest. We can then apply the replace part on that part, and merge these back:
def replace_but_first(text, search, replace):
try:
idx = text.index(search) + len(search)
return text[:idx] + text[idx:].replace(search, replace)
except ValueError: # we did not found a single match
return text
For example:
>>> replace_but_first('X did something. X found it to be good, and so X went home.', 'X', 'Y')
'X did something. Y found it to be good, and so Y went home.'
We can use slicing to produce two string: first one up to (and including) the first element, and the next slice that contains the rest. We can then apply the replace part on that part, and merge these back:
def replace_but_first(text, search, replace):
try:
idx = text.index(search) + len(search)
return text[:idx] + text[idx:].replace(search, replace)
except ValueError: # we did not found a single match
return text
For example:
>>> replace_but_first('X did something. X found it to be good, and so X went home.', 'X', 'Y')
'X did something. Y found it to be good, and so Y went home.'
edited Nov 10 at 14:40
answered Nov 10 at 14:38
Willem Van Onsem
139k16131221
139k16131221
@Ry-: sorry I was confused betweenindex
andfind
.
– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.
– Willem Van Onsem
Nov 10 at 14:41
add a comment |
@Ry-: sorry I was confused betweenindex
andfind
.
– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.
– Willem Van Onsem
Nov 10 at 14:41
@Ry-: sorry I was confused between
index
and find
.– Willem Van Onsem
Nov 10 at 14:40
@Ry-: sorry I was confused between
index
and find
.– Willem Van Onsem
Nov 10 at 14:40
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.– Willem Van Onsem
Nov 10 at 14:41
.find()
strilcty speaking will work as well, although this is a bit ugly, and we save some cycles by not doing a second iteration over the string.– Willem Van Onsem
Nov 10 at 14:41
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53239936%2freplace-all-occurrences-in-string-but-the-first-one%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password