Kyle VanderBeek wrote:
On Sat, Apr 12, 2008 at 04:52:06PM -0400, James Antill wrote:
You can't alter things that you are iterating, the easist fix is:
for directory in directories[:]:
...the others being to create a new list of just what you want, or a list of what needs to go and then do the .remove() calls on that (these methods can be worth it, for large lists).
Actually, I'd contend this technique gets worse as your list size increases. First, you're making a copy pass, doubling your memory footprint, and then a second pass to actually filter the list down to just the elements you want. That will get slower as your list size increases.
Oh, and that reminds me of another way, using the builtin filter():
directories = ['20080412', '20080324', 'blahblah', 'latest-dir',
'rawhide-20080410', 'rawhide-20080411', 'rawhide-20080412' , '20080401']
filter(lambda x: x.startswith('200'), directories)
['20080412', '20080324', '20080401']
Just a note: This will be much slower than the list comprehension for large lists.
That's because function calls have tremendous overhead in python and a lambda is just a function without a name. So using filter you make two function calls for every entry in the list: * lambda [...] * str.startswith()
With a list comprehension you only call str.startswith().
As I tell people, if you want readability, write it out fully (James Antill's solution or even:
newDirectories = [] for directory in directories: if directory.startswith('200'): newDirectories.append(directory) directories = newDirectories
If you want speed and code compactness use a list comprehension.
-Toshio