简体   繁体   中英

Conditional list comprehension

I am trying to gain a better understanding of how list comprehensions work. I have the following function that returns true or false if a number is prime (which I found somewhere on the forum but cant remember where):

import math

def is_prime(n):
    if n % 2 == 0 and n > 2: 
        return False
    for i in range(3, int(math.sqrt(n)) + 1, 2):
        if n % i == 0:
            return False
    return True

if I run:

[x for x in range(2, num) if is_prime(x)]

i get the desired result

[2, 3, 5, 7, 11, 13, 17, 19]

in trying to convert the whole function to a list comprehension I came up with:

[x if not (x%2==0 and x > 2) else x for x in range (2, num) 
     for i in range(3, int(x**(1/2))+1, 2) if not (x%i==0)]

which produces:

[10, 11, 13, 14, 16, 17, 19]

not sure where I am going wrong and would appreciate some help. In truth I think it is better to use the function in this case, but like I said I am trying to understand the list comprehension and its capabilities.

You can do this:

[n for n in range(2, num) if n % 2 != 0 and n > 2 and all(n % i != 0 for i in range(3, int(math.sqrt(n)) + 1, 2))]

although one liner just for the sake of it is not necessarily a good thing. IMO using a prime tester function like you do is better...

NOTE: what doesn't work in your try is that you modified the logic of your outer list comprehension. You still want a structure like [n for n in range(...) if (expression testing if n is prime)] .

The main problem is that you're making a convoluted translation. Try simplifying the original condition so that you return "x if x==2, else x ..." as you've already done. I'm just giving you a leading hint here; from what you've done already, I think you can figure it out.

If not, try simplifying the "else" expression so you learn the logic of that clause. Then I'm sure you'll get it. You're doing well.

There are logical errors in the code above 1/2 evaluates to 0, not to 0.5. To do that, either use 0.5 or 1/2.0 or 1.0/2

Also it does not take care of 2 as a special case. as (for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0)) is not executed

for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0) is also a logical error as whenever this condition is true, it causes multiple entries to be added

the correct way would be

[x for x in range (2, num) if x == 2 or (x > 2 and x % 2 == 1 and len([i for i in range(3, int(x**(1/2.0))+1, 2) if x%i == 0 ])==0)]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM