How to Remove Specific Substrings from a Set of Strings in Python?

I have a set of strings set1, and all the strings in set1 have a two specific substrings which I don't need and want to remove.
Sample Input: set1={'Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad'}
So basically I want the .good and .bad substrings removed from all the strings.
What I tried:

for x in set1:
    x.replace('.good','')
    x.replace('.bad','')

But this doesn't seem to work at all. There is absolutely no change in the output and it is the same as the input. I tried using for x in list(set1) instead of the original one but that doesn't change anything.

9 Answers

Strings are immutable. str.replace creates a new string. This is stated in the documentation:

str.replace(old, new[, count])

Return a copy of the string with all occurrences of substring old replaced by new. [...]

This means you have to re-allocate the set or re-populate it (re-allocating is easier with a set comprehension):

new_set = {x.replace('.good', '').replace('.bad', '') for x in set1}

NOTE: If you intend to change prefix or suffix str.removeprefix('prefix') str.removesuffix('suffix') respectively should be used.

1
>>> x = 'Pear.good'
>>> y = x.replace('.good','')
>>> y
'Pear'
>>> x
'Pear.good'

.replace doesn't change the string, it returns a copy of the string with the replacement. You can't change the string directly because strings are immutable.

You need to take the return values from x.replace and put them in a new set.

1

In Python 3.9+ you could remove the suffix using str.removesuffix('mysuffix'). From the docs:

If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string

So you can either create a new empty set and add each element without the suffix to it:

set1  = {'Apple.good', 'Orange.good', 'Pear.bad', 'Pear.good', 'Banana.bad', 'Potato.bad'}

set2 = set()
for s in set1:
   set2.add(s.removesuffix(".good").removesuffix(".bad"))

Or create the new set using a set comprehension:

set2 = {s.removesuffix(".good").removesuffix(".bad") for s in set1}
   
print(set2)

Output:

{'Orange', 'Pear', 'Apple', 'Banana', 'Potato'}
0

All you need is a bit of black magic!

>>> a = ["cherry.bad","pear.good", "apple.good"]
>>> a = list(map(lambda x: x.replace('.good','').replace('.bad',''),a))
>>> a
['cherry', 'pear', 'apple']

When there are multiple substrings to remove, one simple and effective option is to use re.sub with a compiled pattern that involves joining all the substrings-to-remove using the regex OR (|) pipe.

import re

to_remove = ['.good', '.bad']
strings = ['Apple.good','Orange.good','Pear.bad']

p = re.compile('|'.join(map(re.escape, to_remove))) # escape to handle metachars
[p.sub('', s) for s in strings]
# ['Apple', 'Orange', 'Pear']

You could do this:

import re
import string
set1={'Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad'}

for x in set1:
    x.replace('.good',' ')
    x.replace('.bad',' ')
    x = re.sub('\.good$', '', x)
    x = re.sub('\.bad$', '', x)
    print(x)
6
# practices 2
str = "Amin Is A Good Programmer"
new_set = str.replace('Good', '')
print(new_set)

 

print : Amin Is A  Programmer
6

I did the test (but it is not your example) and the data does not return them orderly or complete

>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> newind = {x.replace('p','') for x in ind}
>>> newind
{'1', '2', '8', '5', '4'}

I proved that this works:

>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> newind = [x.replace('p','') for x in ind]
>>> newind
['5', '1', '8', '4', '2', '8']

or

>>> newind = []
>>> ind = ['p5','p1','p8','p4','p2','p8']
>>> for x in ind:
...     newind.append(x.replace('p',''))
>>> newind
['5', '1', '8', '4', '2', '8']

If list

I was doing something for a list which is a set of strings and you want to remove all lines that have a certain substring you can do this

import re
def RemoveInList(sub,LinSplitUnOr):
    indices = [i for i, x in enumerate(LinSplitUnOr) if re.search(sub, x)]
    A = [i for j, i in enumerate(LinSplitUnOr) if j not in indices]
    return A

where sub is a patter that you do not wish to have in a list of lines LinSplitUnOr

for example

A=['Apple.good','Orange.good','Pear.bad','Pear.good','Banana.bad','Potato.bad']
sub = 'good'
A=RemoveInList(sub,A)

Then A will be

1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

David Miller

David Miller

Executive Financial & Market Analyst

David Miller brings 15 years of experience in global economics, personal finance strategy, and market dynamics. He specializes in turning complex economic trends into actionable insights for everyday readers.

Share this article
Twitter Facebook Pinterest