Reputation: 295
I am trying to build a simple function to censor a specific word in a sentence. For example "hello hello hi"
to "***** ***** hi"
if I feed censor("hello hello hi", "hello")
. Assuming I will not receive punctuation and sentences with upper case letters or empty strings.
After researching online I understand there is simpler solution, for example:
def censor(text, word):
return text.replace(word, "*" * len(word))
I still want to understand from a learning perspective, what I did wrong in the below more complicated code.
def censor(text,word):
split_text = text.split()
length = len(word)
for item in split_text:
if item == word:
item = ("*" * length)
else:
item = item
return " ".join(split_text)
Upvotes: 4
Views: 4358
Reputation: 15226
The solution I came up with was a little simpler and gets the job done.
1.I make sure both arguments are a string and then check if the word is in the text string. 2.Then if the word is in the text string I get the length of the word. 3.Then I replace the word inside the string with * however many times the word is long.
def censor(text,word):
t=str(text)
w=str(word)
if w in t:
l=len(w)
item = ("*" * l)
return t.replace(w,item)
else:
return t
Upvotes: 2
Reputation: 4656
There is a difference between the variable and the value that the variable has at a given point at the running time. The statement
for item in split_text:
Sequentially assigns the value of each item in split_text
to item
.
item = ("*" * length)
Changes item
to a new value computed from its length. But split_text
remains exactly what it was at the beginning.
Upvotes: 0
Reputation: 1112
As mentioned other answers, you can't change list value in for loop.
You can access list value using enumerate
, get index of value. And, you don't need else
because you don't change value.
for idx, item in enumerate(split_text):
if item == word:
split_text[idx] = ("*" * length)
Upvotes: 1
Reputation: 1126
You probably see what you did wrong based on the comments. But you might not understand why (and based on your question I think you may be interested to know).
In python you can roughly divide the datatypes into 2 categories: mutable and immutable. The basic difference is that you can create references to mutable type variables whereas you can only pass around the values of immutable type variables. Refer to this question for examples.
In your case you are iterating through a list containing strings. Strings happen to be immutable. So when you change item
it won't have any effect on the corresponding element in split_text
.
If instead you were iterating through a list of lists, you would actually be able to change the list elements using the placeholder variable.
Illustrated with an example:
x = [["foo"],["foo","bar"]]
for i in x:
if len(i) == 1:
i[0] += "bar"
else:
i.append("foobar")
print(x) #[["foobar"],["foo","bar","foobar"]]
Hope this helps! :)
Upvotes: 1
Reputation: 1480
The for-loop in your code does not reference or modify the actual item in split_text
. Try this:
for item in range(len(split_text)):
if item == word:
split_text[item] = ("*" * length)
...
Also, it is generally considered poor practice to modify a list within a loop. See this post: How to modify list entries during for loop?
Upvotes: 1