Anil_M
Anil_M

Reputation: 11443

convert double for loop with lambda function and break to list comprehension

I've following code that I need to convert to list-comprehension (one liner). However, I am unable to do so. The code calculates prime numbers up-to input range of A.

def sieve(A):    
    l = []
    f = lambda x : int(x**0.5)
    for p in range(2,A+1):        
        for i in range(2, f(p) + 1):
            if p % i == 0:
                break
        else:
            l.append(p)
    return l

So far I've following which does not work. Especially the break within for-loop is throwing me off.

list(set([val for sublist in [[p  for i in range(2, f(p) + 1) if p %i != 0 ] for p in range(2,A) ] for val in sublist]))

EDIT
Adding constraints for the problem. The code can only be one statement, without eval or exec. The code must be at most 160 character long.

Upvotes: 1

Views: 2076

Answers (2)

kaza
kaza

Reputation: 2327

[p for p in range(2,A+1) if next((i for i in range(2, int(p**0.5) + 1) if (p % i) == 0),None)==None]

Code is 100 chars long.
We use next() to break out of the iteration.
Explanation

def sieve(A):
  [p for p in range(2,A+1) if getFirstDiv(p)==None]

def getFirstDiv(p):
  next(divIter(p),None)

def divIter(p):
  return (i for i in range(2, int(p**0.5) + 1) if (p % i) == 0)

OUTPUT

15 --> [2, 3, 5, 7, 11, 13]
10 --> [2, 3, 5, 7]

Upvotes: 1

Robbie
Robbie

Reputation: 4872

This one liner will do it:

[r for r in [i*all([i if i%j!=0 else 0 for j in range(2,i)]) for i in range(2,x)] if r>0]

You just need to set x (the maximum value).

Note: it is not particularly efficient, although I'm guessing efficiency isn't the aim of this question.

Explanation (expanded code):

filtered = []
primes = []

for i in range(2,x):
    # Check that all numbers up to i do not divide i
    # I realise we only need to check up to int(sqrt(i))
    condition = all([i if i%j!=0 else 0 for j in range(2,i)])

    # Exploit Python's treatment of bool: number*True = number and number*False=0
    filtered.append( i*condition )


for r in filtered:
    # Take out all the zeros
    if r>0:
        primes.append(r)

Upvotes: 1

Related Questions