10.censor


#1

is there any way to solve this puzzle without ruining this code ??

the error is:Oops, try again. Your code looks a bit off--it threw a "'str' object has no attribute 'insert'" error. Check the Hint if you need help!

def censor (text , word):
    b = text.index(word)
    a = "*"*len(word)
    text.insert(int(b) , a)
    text.remove(word)

#2

You shouldn't have any line preceding the code. Check my edit.


#3

ok done :smiley: but how to solve this?


#4

And the error message is very clear. Strings in python do not have an insert method.

You will have to use list slicing to get parts of the text before and after the censored word and then concatenate them all with the asterisk string in between. Here's something to get you started:

start = text[0: b] # string before the word

P.S. Your code will only work for one instance of the word in text. You will need to use a while loop to replace all occurrences.


#5

can you explain more ??? I didn't get it :confused:


#6

.insert method exists for lists. You are trying to use it on a string, so it obviously won't work. You will have to use list/string slicing the way I mentioned or the solution given in the hint.

Which part of my reply are you unsure about? .insert method, string slicing or the "PS" part.


#7

string splicing and ps part (if that won't annoy you) :blush:


#8

Explaining string slicing would be reinventing the wheel since a good explanation exists on the official docs - https://docs.python.org/2/tutorial/introduction.html#strings Just scroll down a little to the string indexing part and carefully study it while experimenting on repl.it when you need to.

And you must have learned about while loops already. Just check if text.index(word) is not equal to -1. That would mean the word exists and you have to replace it.

And helping users doesn't annoy me. Especially when they try to create some new solution on their own :smiley:


#9

Thanks for Reply .. I was busy for few weeks in exams .. so I am sorry for late Reply
look if have tried this

def censor (text,word):
    b = text.index(word)
    a = "*"*len(word)
    start = text[0: b] # string before the word
    end = text[b :]
    c = start + a + end
    return c

but the result was an error :Oops, try again. Your function fails on censor("hey hey hey","hey"). It returns "hey hey hey" when it should return " *** ***".

I don't have any idea on how to loop this function to make all the words star (I know how to write aloop but i didn't know how to try the loop you mentioned above I can't imagine the mechanism how it works in this code)


#10

Hi @coderockstar13753,

Here's a pseudo code, to help you understand what I mean:

store index of `word` in `b`
if `b` != -1: # means that word exists
    store the text before b in `x`
    store the text after (b + length of word) in `y`
    concatenate x, some stars ("*") and y, store back into text
    again call censor passing the new text value and same `word`, store result in text # to repeat the above process
    return the text returned by the call above
else:
    return the text # no changes to make since word doesn't exist

As you can see I have given up the loop since that confused and utilized a different type of solution that involves censor calling itself repeatedly. Now try converting this pseudocode to actual code. Remember to keep experimenting on repl.it

Let me know if this is still confusing, I will try to to give pseudo code for while loops then.

Hope it helps! :smiley:


#11
def censor (text,word):
    b = text.index(word)
    if b != -1 :
        a = "*"*len(word)
        start = text[0: b] # string before the word
        end = text[b+len(word) :]
        c = start + a + end
        return c
    else :
        return text

I tried what you told me but I didn't understand those two lines so I couldn't write them in code and the code gives me this error, Oops, try again. Your function fails on censor("hey hey hey","hey"). It returns "*** hey hey" when it should return "*** *** ***".

again call censor passing the new text value and same word, store result in text # to repeat the above process
return the text returned by the call above


#12

I think I've got a much easier solution:
import string
def censor(text, word):
censorword = '*' * len(word)
censortext = string.replace(text, word, censorword)
return censortext

that's it!!


#13

@coderockstar13753 You are nearly there! :smiley: All you need is:

def censor (text,word):
    # additionally, `.index` gives error when `word`
    # is not present in `text`, so use below condition
    if word in text: 
        a = "*" * len(word)
        b = text.index(word)
        start = text[0: b] # string before the word
        end = text[b+len(word): ]
        c = start + a + end
        return censor(c, word) # this line is all you need
    else:
        return text
        
print censor("hey hey hey", "hey")

I am giving you a dry run of the code to see how it works:

censor("hey hey hey", "hey")
-- word is in text; if-branch executed
-- c = "*** hey hey"
-- return censor("*** hey hey", "hey")
-- >- word is in text; if-branch executed
-- -- c = "*** *** hey"
-- -- return censor("*** *** hey", "hey")
-- -- >- word is in text; if-branch executed
-- -- -- c = "*** *** ***"
-- -- -- return censor("*** *** ***", "hey")
-- -- -- >- word is NOT in text; if-branch not executed
-- -- -- -- return "*** *** ***"

Read it carefully a few times. Experiment on the repl. If you are uncomfortable with this, I'll give you a while loop solution :slightly_smiling:

And, @ignasiseguravicente, yes, you've indeed got a much easier solution, but as you'll see, we are debugging and helping @coderockstar13753 understand the closest alternative to his original solution that works well. While you have utilized an existing built-in method, we are discussing the possible implementation of that built-in method itself. Any way, kudos to you for having figured out the easier solution :slightly_smiling:


#14

it works!

import string
def censor(text, word):
    replacement = "*" * len(word)
    ls = string.split(text)
    for i in range(0, len(ls)):
        if ls[i] == word:
           ls[i] = replacement
    return string.join(ls)

#15

@gaurangtandon thank you very much for your patience it worked :smiley:
@ignasiseguravicente thanks for your advice :smiley:


#16

.this a nice idea I always use a for loop to add every letter to a list then do work on it the print joining them all i also liked if == then =

:clap:


#17

@coderockstar13753 I am very glad that you are able to understand the concept. Wish you best of luck for future exercises! :smiley:


#18

This really only needs one line (two if you count the function definition):

def censor(text, word):
    return " ".join([w if w != word else "*"*len(w) for w in text.split()])

#19

@envysquared Wow! It's so simple and works. But I don't understand the syntax of this one line, can you explain it? thanks!


#20

It's a list comprehension. There's a good explanation with many examples in the Python docs: https://docs.python.org/2/tutorial/datastructures.html#list-comprehensions