1

My code reads a directory and stores the filename with extention into a list. What I am trying to do is get rid of the extention with replace. However, it is not saving into the list.

 print projectFilenames

 for f in projectFilenames:
  print f
  f = f.replace('.txt','')
  f = f.replace('.mdown','')
  f = f.replace('.markdown','')
  print f

 print projectFilenames

and this is my output

['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']
2010-10-30-markdown-example.txt
2010-10-30-markdown-example
2010-12-29-hello-world.mdown
2010-12-29-hello-world
2011-1-1-tester.markdown
2011-1-1-tester
['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']

What am I doing wrong?

5 Answers 5

7

The list doesn't change, because you aren't updating it. You aren't touching the projectFilenames list in any way (nor the strings in the list. Python variables are not pointers) Here is one way to do it:

newlist = []
for f in projectFilenames:
    f = f.replace('.txt','')
    f = f.replace('.mdown','')
    f = f.replace('.markdown','')
    newlist.append(f)

projectFilenames = newlist

Also, look at the os.path module, there are functions there to cut off file extensions. os.path.splitext() specifically. So another way of doing it would be:

newlist = []
for f in projectFilenames:
    f = os.path.splitext(f)[0]
    newlist.append(f)

projectFilenames = newlist

That in turn can be simplified to (and made compliant with PEP 8):

>>> import os
>>> project_filenames = ['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']
>>> project_filenames = [os.path.splitext(f)[0] for f in project_filenames]
>>> project_filenames
['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']
Sign up to request clarification or add additional context in comments.

Comments

4

You are replacing the f object not the projectFileNames , do it like this;

>>> [x.split(".")[0] for x in projectFileNames]
['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']

Removes the extension.

Comments

4

list slice replacement using list comprehension (updates contents of original list):

l[:] = [f.replace('.txt','').replace('.mdown','').replace('.markdown','') for f in l]

splitext (suggested by @lennart, @ sukhbir)

import os
l[:] = [os.path.splitext(f)[0] for f in l]

using enumerate:

import os
for idx, filename in enumerate(l):
    newfilename = os.path.splitext(filename)[0]
    if newfilename != filename:
        l[idx] = newfilename

Anecdotal: splitext()[0], str.replace('.txt') and str.split('.txt')[0] return the original string untouched if it has no extension or match. (at least in Python 2.6)

6 Comments

The OP asked for updating the list. l points to a list, [:] updates that list. l = newlist will replace l's reference to a new list, but not any others. l = list a = [1,2]; b = a; a = [3, 4]; b == [1, 2]. l[:] = list a = [1, 2]; b = a; a[:] = [3, 4]; b == [3, 4]. The OP may not actually require this, I like to point it out as it is often overlooked.
@Lennart, from looking at your profile, I hope I didn't insult you with my last comment.
OK, I see your point, the list could have been passed in as a parameter, for example.
For good or bad, the OP has more or less asked to update the list in place.
Your l[:] = <list comprehension with modified elements> options are the most Pythonic, using the best Python idiom. Using enumerate is a poor second, mirroring in-place array modification as would be done in a compiled language like C. Learn the idioms, build a new list (or update in place with [:] slicing) with a list comprehension.
|
2

As mentioned in other answers, the reason the filename list doesn't change is because your code doesn't change it. There's a number of ways of fixing that, including building a new list and replacing the original with it.

I think the simplest approach would be to just modify the list as you're iterating over its elements (but you have to be careful when doing this that you don't modify parts of the list not yet seen). Python has a built-in function called enumerate() which makes this kind of task easy to code. What enumerate() does is return an "iterator" object which counts out the items as it provides each one from the sequence -- so the count is also the item's index in that sequence, and when necessary that index can be used to update the corresponding list element.

Since your code is dealing with filenames, it could be improved further by making use of the built-in module named os.path which is available for dealing with paths and filenames. That module has a splitext() function for breaking filenames into two parts, the "root" and the extension. It's called root instead of filename in the documentation because it could have directory path information prefixed onto it.

If your code was rewritten using enumerate() and os.path.splitext() it might look something like this:

import os
projectFilenames = ['2010-10-30-markdown-example.txt',
                    '2010-12-29-hello-world.mdown',
                    '2011-1-1-tester.markdown']

for i,f in enumerate(projectFilenames):
    root,ext = os.path.splitext(f)
    if ext in ('.txt', '.mdown', '.markdown'):
        projectFilenames[i] = root  # update filename list leaving ext off

print projectFilenames
# ['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']

If you wanted to remove all file extensions, not just specific ones, you could just change the if ext in ('.txt', '.mdown', '.markdown'): to just if ext:.

2 Comments

+1 because this covers everything. However, a tuple should be better than a list in this case (if ext in ...). Not only is it faster to create but better because you won't modify this.
@sukhbir: Good point -- thanks -- answer updated accordingly.
1

Such operations on files should always be done with os.path.splitext. Because it is easier to maintain, portable and you don't have to reinvent the wheel.

>>> os.path.splitext('/home/Desktop/foo.py')[0]
'/home/Desktop/foo'

So say that you have a list, x, which has all all the files:

[os.path.splitext(files)[0] for files in x]

2 Comments

Wild guess: Because you aren't actually answering the question?
I suggested a better method of doing it. Anyways, it's ok. I don't mind the downvote, I maybe wrong, but if just a reason was given it helps in knowing where.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.