pythonfilterany

Does filter have a way to export the "list" one element at a time?


On a practice exercise about prime numbers I found out that filter does not return a list itself and I need to do:

list(filter())

to obtain that list.

I do the exercise twice, once with a for loop:

def is_prime_for(n:init):
    if n <=3:
        return True
    else:
        m=list(range(2,n//2+1))     #+1 on the range for evade a bad result if 'n==4'    
    for i in m:
        if n % i == 0:
            return False
    else:
        return True
value = 864203                     
print(is_prime_for(value))

other time with filter and lambda:

def is_divisible(num1:float,num2:float):
    if num1 % num2 == 0:
        return True
    else:
        return False

def is_prime(num:int):
    if list(filter(lambda x: is_divisible(num,x), list(range(2,num//2+1)))) != []:
        return False
    else:
        return True
value = 864203                 #Same prime number that i found on google
print(is_prime(value))

Later I re-use the code for higher order functions and find that my "compact" filter and lambda function takes double time than for function to execute and much more with a "False" number (for example a number that can be divided by 2).

I can understand the double time because it goes through the list twice instead of once but in the case of the "False" number I thought that filter() is going to give me a empty list until the first number appear but that's not the case, list is "empty" until filtering ends.

Does anyone know a way to "update" filtered items list one as a time instead at the end of the filtering?

That's my code now with the higher order function that show the execute time:

import time  
  
def timeis(func):   #Decorator that reports the execution time.
    def wrap(*args, **kwargs): 
        start = time.time() 
        result = func(*args, **kwargs) 
        end = time.time() 
          
        print(func.__name__, end-start) 
        return result 
    return wrap 

def is_divisible(num1:float,num2:float):
    if num1%num2 == 0:
        return True
    else:
        return False
      
@timeis
def is_prime(num:int):
    if list(filter(lambda x: is_divisible(num,x),list(range(2,num//2+1)))) != []:  #+1 on the range for evade a bad result if 'n==4'
        return False
    else:
        return True
    
@timeis
def is_prime_for(n : int = 2):
    if n <= 3:
        return True
    else:
        m = list(range(2,n//2+1))
    for i in m:
        if n%i == 0:
            return False
    else:
        return True 
    
value = 864203           #A prime number that i found on google
#print(is_prime(value))    #That is used for prove the value find on google for no "false" positives
is_prime(value)
is_prime_for(value)

and that's the output:

is_prime 0.06304740905761719
is_prime_for 0.02378678321838379

**

EDIT

**

After testing with the code from answer and coments the code end like this:

import time
  
def timeis(func):  #Decorator that reports the execution time.
    def wrap(*args, **kwargs): 
        start = time.time() 
        result = func(*args, **kwargs) 
        end = time.time() 
          
        print(func.__name__, end-start) 
        return result 
    return wrap 

def is_divisible(num1:float,num2:float):
    if num1%num2 == 0:
        return True
    else:
        return False
 
@timeis
def is_prime(num:int):
    if any(is_divisible(num,x) for x in range(2,int(num**0.5+1.01))):   #Improved math with @Trincot answer and the help of @OneCricketeer on comments section
        return False
    else:
        return True

@timeis
def is_prime_all(num: int):                           #@Trincot answer
    return all(num%x for x in range(2, int(num**0.5+1.01)))

@timeis
def is_prime_all_mod(num: int):                       #@Trincot answer 'moded', it's faster on "False" numbers
    return all(num%x for x in range(2, num//2+1))

@timeis
def is_prime_for(n : int = 2):       #Improved math with @Trincot answer
    if n <= 3:
        return True
    else:
        m = range(2,int(n**0.5+1.01))
    for i in m:
        if n%i == 0:
            return False
    else:
        return True 
    
@timeis
def is_prime_while(n : int = 2):    #Improved math with @Trincot answer
    if n <= 3:
        return True
    else:
        x = int(n**0.5+1.01)
        i = 2
        while i < x:
            if n % i == 0:
                return False
            i+=1
        else:
            return True 
    
#value = 28122221                 #A prime number that i found on google
value = 28122222                #A "false" prime number for tests
#print(is_prime(value))  
is_prime(value)
is_prime_all(value)
is_prime_all_mod(value)
is_prime_for(value)
is_prime_while(value)

With an output with a "Real" prime number:

is_prime 0.00029087066650390625
is_prime_all 0.0001399517059326172
is_prime_all_mod 0.607919454574585
is_prime_for 0.0001266002655029297
is_prime_while 0.00017380714416503906

And the output if a number is not prime like:

is_prime 1.0013580322265625e-05
is_prime_all 7.152557373046875e-06
is_prime_all_mod 1.6689300537109375e-06
is_prime_for 1.1920928955078125e-06
is_prime_while 4.76837158203125e-07

Solution

  • There are a few things to improve here:

    That brings us to this version of the code:

    @timeis
    def is_prime(num: int):
        return all(num%x for x in range(2, int(num**0.5+1.01)))
    

    Further improvements are possible.