Hi,
I need some assistance trying to delete elements in list.


Your task is to write a function, called bawdlerize(<sent>, <word>), which removes an unsavory word,
<word>, from a sentence, <sent>. Use the "del" operator on lists for this function. Example:
s = ["now", "is", "the", "time", "for", "all", "good", "men", "to",
"come", "to", "the", "aid", "of", "their", "parties"]

bawdlerize(s, "to")
s = ["now", "is", "the", "time", "for", "all", "good", "men", "come",
"the", "aid", "of", "their", "parties"]

Here is what I did so far

s = list(raw_input("enter the the sentence you want in a list"))


def bawdlerize(s,w):
    for i in range(len(s)):
        del s[w]
    return s

I changed the variables <sent> to s and <word> because for some reason python doesn't accpept < > these angle signs for substitution as variables. I put the list function outside the scope of the raw_input function because raw_input function only accepts strings.

This seems to be an easy problem but I can't seem to figure out what I am doing wrong thanks.

First, a bit of historical information: http://en.wikipedia.org/wiki/Thomas_Bowdler
The word is actually bowdlerize. That's fun, but not important.

Second, a list is indexed by an integer, not a key, so you want something like

for i in range(len(s)):
  ... s[i] ... # [B]not[/B] s[w]

Third, you will need to call your bawdlerize(s,w) passing it the sentence s , and the word to remove w Fourth: You need to use the string method split() to convert the sentence into a list

A way to do it without using del (so it will not help your asignement:

def bowdlerize(sentence, list_of_bad):
  """
  sentence is a string
  list_of_bad is a list containing words to be removed from sentence
  returned value is a list of words from sentence that are not in list_of_bad
  """
  original_list = sentence.split()
  return [x for x in original if x not in list_of_bad]

Finally: Imagine that you had to actually do this for real text, in real time (I had to write a program to do that). I got a real education... How would you handle "fuh-q"? or how about "SH1T" (notice the digit '1')? It gets better: How do you deal with people who may be writing objectionable things in several different languages?
http://www.denverpost.com/dontmiss/ci_12097797 http://media.ohio.com/documents/denied+plates+1-1-07+-+1-29-09.pdf (and many many more)

First, a bit of historical information: http://en.wikipedia.org/wiki/Thomas_Bowdler
The word is actually bowdlerize. That's fun, but not important.

Second, a list is indexed by an integer, not a key, so you want something like

for i in range(len(s)):
  ... s[i] ... # [B]not[/B] s[w]

Third, you will need to call your bawdlerize(s,w) passing it the sentence s , and the word to remove w Fourth: You need to use the string method split() to convert the sentence into a list

A way to do it without using del (so it will not help your asignement:

def bowdlerize(sentence, list_of_bad):
  """
  sentence is a string
  list_of_bad is a list containing words to be removed from sentence
  returned value is a list of words from sentence that are not in list_of_bad
  """
  original_list = sentence.split()
  return [x for x in original if x not in list_of_bad]

Finally: Imagine that you had to actually do this for real text, in real time (I had to write a program to do that). I got a real education... How would you handle "fuh-q"? or how about "SH1T" (notice the digit '1')? It gets better: How do you deal with people who may be writing objectionable things in several different languages?
http://www.denverpost.com/dontmiss/ci_12097797 http://media.ohio.com/documents/denied+plates+1-1-07+-+1-29-09.pdf (and many many more)

thanks so much for your hint. However I still can't get python to print the list without the designated deleted word. When I do run the program it just prints the string inputted into a list. From what I am reading it should delete w because I said for all the elements in s( which is a list of strings), if i is not present in the list, delete w. Then I put return s so that if returns the value with the deleted word.

What am I doing wrong. Any hint would be much appreciated.

import string

sentence=raw_input("Enter a string")
s= sentence.split()
def bowdlerize(s,w):
    for i in range(len(s)):
        if i not in range(len(s)):
            del w
            
        return s

Edited 6 Years Ago by G-nerd: n/a

I am still likely to do this kind of thing by building a new tuple (I have heart tuple is faster to construct than list) of words like this instead of deleting. I do not know how much slower it would be:

def bawdlerize(s,w):
    return tuple(word for word in s if word.lower() not in w)

s = ["now", "is", "the", "time", "for", "all", "good", "men", "to",
"come", "to", "the", "aid", "of", "their", "parties"]

print bawdlerize(s, ("to",))

print bawdlerize(s, ("to",'the'))

Tony: The problem specifies using del. Which is probably wrong for working code...

All: I fear that deleting in the course of a for item in aList: loop might cause trouble. A classic C-style linked list would be ok, but an array-based list would likely have trouble: After you delete the item at location M and then advance your pointer to location M+1, you have skipped looking at the item next after M, because it 'slid left' into the location still indexed by M. (Goes off and checks): Yes, it is a problem.

G-nerd: You have two problems: First, the problem mentioned above, Second, you are not deleting the item in the list, but deleting the item itself. To delete, say, the 5th item in the list s: del(s[5]) . However, because of the trouble mentioned above, you can't do it the simple way. There are two outs:

  1. Delete in reverse order Removing the 10th item invalidates the indexes for items formerly at 11 and above, but does not invalidate indexes in range(10) .
  2. Repeat single deletes until none are found.

Of the two, the first is faster, the second may be easier to understand, but much slower if multiple deletes per list. The third option (mentioned by Tonyjv) is better. Much better for a problem of this size (not so obviously better if the list has 100s of thousands of items)

(proof of problem:)

s = [x for x in range(10)
print(s)
for i in range(5):
  del(s[3])
print s

Edited 6 Years Ago by griswolf: n/a

thanks so much for your hint. However I still can't get python to print the list without the designated deleted word. When I do run the program it just prints the string inputted into a list. From what I am reading it should delete w because I said for all the elements in s( which is a list of strings), if i is not present in the list, delete w. Then I put return s so that if returns the value with the deleted word.

What am I doing wrong. Any hint would be much appreciated.

import string

sentence=raw_input("Enter a string")
s= sentence.split()
def bowdlerize(s,w):
    for i in range(len(s)):
        if i not in range(len(s)):
            del w
            
        return s

Let's see what you do. You increase i from 0 to len(s) and you delete the variable name w if i is not in range of 0 to len(s). So del w is never executed.

You can only delete an item in a list with an index (more precisely a slice).
So if you want to delete the first item in the list s , you have to write del s[0].
Keep in mind, that if you delete the first item, all the indexes are shifted. So if you delete the first item twice, you remove the first two item.

It is very unpractical to use del for that kind of problem, unless the list is very long.
If you must do it, you should handle the shifting, I think.

s = ["now", "is", "the", "to", "time", "for", "all", "good", "men", "to",
     "come", "to", "the", "aid", "of", "their", "parties"]

def bawdlerize(li, w):
    sli=[]#list of indexes to be deleted
    for i,k in enumerate(li):
        if k==w:
            sli.append(i)
    c=0#shifting
    for ind in sli:
       del li[ind-c]
       c+=1
    
bawdlerize(s, "to")
print s == ["now", "is", "the", "time", "for", "all", "good", "men", "come",
"the", "aid", "of", "their", "parties"] # must be true

Edited 6 Years Ago by slate: n/a

For del I would try to go through the list in reverse and del directly to avoid problem of shift.

Exactly. If you must use del (in order to satisfy the pointy haired boss, I suppose), then working from largest index to smallest is the least cost option. It even saves a little work on the shifting: Assuming you somehow know which indices are needed, if you start with the small index, you are making Python work to shift some items that will later be deleted; but if you start at the large index, those items are already gone by the time you delete below them, shifting only the 'good' items.

But del is probably never the "best" option (for some meaning of the word "never") since it has side effects on the list: Usually a bad idea; since it costs order of length squared (see below); and since it is hard to get right.

Lets calculate some big-O costs: For some deletes in the list, you have to walk the list to find the targets, which takes [tex]O(n)[/tex] steps, and for each del, you incur about [tex]n/2[/tex] shifts on average, for a cost that looks like [tex]Cn^2[/tex] for some [tex]C[/tex] that is almost a power of [tex]1/2[/tex]. If you construct a new tuple as suggested above, you still have to walk the list, and you have to copy an item [tex]n - C[/tex] times for a total cost that looks like [tex]n+n-C[/tex] where [tex]C[/tex] is the number of "deletes". For small lists with few deletes, del is a faster option, but when the size gets larger; or if the deletes are earlier in the list or there are many of them, then constructing a new list is better (not counting the issue of available memory)

Exactly. If you must use del (in order to satisfy the pointy haired boss, I suppose), then working from largest index to smallest is the least cost option. It even saves a little work on the shifting: Assuming you somehow know which indices are needed, if you start with the small index, you are making Python work to shift some items that will later be deleted; but if you start at the large index, those items are already gone by the time you delete below them, shifting only the 'good' items.

But del is probably never the "best" option (for some meaning of the word "never") since it has side effects on the list: Usually a bad idea; since it costs order of length squared (see below); and since it is hard to get right.

Lets calculate some big-O costs: For some deletes in the list, you have to walk the list to find the targets, which takes O(n) steps, and for each del, you incur about n/2 shifts on average, for a cost that looks like Cn^2 for some C that is almost a power of 1/2. If you construct a new tuple as suggested above, you still have to walk the list, and you have to copy an item n - C times for a total cost that looks like n+n-C where C is the number of "deletes". For small lists with few deletes, del is a faster option, but when the size gets larger; or if the deletes are earlier in the list or there are many of them, then constructing a new list is better (not counting the issue of available memory)

Yes, see: http://bytes.com/topic/python/answers/101848-list-implementation

This article has been dead for over six months. Start a new discussion instead.