[Tutor] list comprehension, testing for multiple conditions

Peter Otten __peter__ at web.de
Fri Aug 24 08:55:05 CEST 2012


Pete O'Connell wrote:

> Hi, I have tried to simplify things and am running into a bit of trouble.
> What i am really trying to do is: Keep all the lines starting with "v "
> and then delete those lines whose modulus 5 don't equal zero
> 
> I have written it like this which seems to take a really long time (a
> couple of  minutes when iteration over a folder with 200 files to parse)
> #####################################
> with open(theFilePath) as lines:
>     #keep only the lines beginning with "v " (this works)
>     theGoodLines = [line.strip("\n") for line in lines if "v " ==
> line[0:2]]
>     theLinesAsListSubset = []
>     for i in range(len(theGoodLines)):
>         nuke.tprint(i)
>         if i%5 != 0:
>             continue
>         elif i%5 == 0:
>             theLinesAsListSubset.append(theGoodLines[i])
> ########################################
> 
> I think it would be better to include the modulud test within the original
> list comprehension but I am not sure how to access the index of "line":
>     #something like this is a sketch of what I mean (I know it's wrong)
>     theGoodLines = [line.strip("\n") for line in lines if "v " ==
> line[0:2] and line.getIndex() % 5 == 0]
> 
> 
> Do I need enumerate for this maybe?

With enumerate() you need two steps, but you can use a generator expression 
(which doesn't materialize the list as you might remember):

# low memory consumption
good = (line for line in lines if line.startswith("v "))
every_fifth = [line.strip("\n") for index, line in enumerate(prefixed) 
        if not index % 5]

Alternatively you can build the good list and apply slicing:

# simple/fast
good = [line.strip("\n") for line in lines if line.startswith("v ")]
every_fifth = good[::5]

Finally there's itertools.islice() which helps you combine the advantages of 
both:

# low memory consumption, fast
good = (line.strip("\n") for line in lines if line.startswith("v "))
every_fifths= list(itertools.islice(good, 0, None, 5))




More information about the Tutor mailing list