0

I wanted to improve my python so I decided to implement some math functions. I implemented the integer factorization as follows:

def integer_factorization(x):
   if isprime(x):
       return [x]
   factors = []
   for i in sieve_eratosthenes(x):
       while x % i == 0:
           int_fact.append(i)
           x /= i
   return factors

I want to return all the factors of x in a list.

Now I wonder if I can do it with list comprehension as I return a list in any case, whether it adds readability to the function or not (the use of such syntactic sugar is what I meant with when I said I want to improve my python).

I noticed that it is not possible (or I just don't know how) to use a while-loop in list-comprehension as you would use a for-loop in it.

For example:

#filling l with items of lst with a for loop
def foo1(lst):
   l = []
   for i in list:
      l.append(i)
   return l

#filling l with items of lst with a while loop
def foo2(lst):
   l = []
   i = 0
   while i < len(lst):
      l.append(lst[i])
   return l

foo1() can be "transformed" into

def foo1(list):
   return [x for x in list]

But is it possible to use this list-comprehension as I did with foo1() also with foo2()?

If yes how can I rewrite integer_factorization() into something like:

def integer_factorization(x):
   return [x if isprime(x) else for i in sieve_eratosthenes(x) #while x%i==0 ...]

If this is not possible, why is it like that? In what way does a for-loop differ from a while-loop that it can not be used in list-comprehension?

IPiiro
  • 97
  • 1
  • 9
  • Does this answer your question? [Using 'while' loops in a list comprehension](https://stackoverflow.com/questions/42707435/using-while-loops-in-a-list-comprehension) – lorenzozane Nov 18 '20 at 11:48
  • I read this before I asked here, but it didn't helped me to understand why I can't use while in list-comprehension or how to do it – IPiiro Nov 18 '20 at 11:50
  • Which bit of the linked question/answers do you not understand? – quamrana Nov 18 '20 at 11:53
  • My function is working and doing its job as it is in the first chunk of code. My main problem is that I want to understand why while-loops can't be used that way. – IPiiro Nov 18 '20 at 11:57
  • So it is the python language that requires a for-loop in that case. I just wondered about the reasoning behind it because both of them are loops – IPiiro Nov 18 '20 at 12:09
  • 1
    use ```map``` and recursion ? – coderoftheday Nov 18 '20 at 20:11
  • For rewriting `integer_factorization()`? Can you give me a hint about how you would do this? – IPiiro Nov 19 '20 at 00:27

1 Answers1

1

There are a couple things to look at that might help you understand. First, your example of a while loop was actually an infinite loop.

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    i = 0
    while i < len(lst):
        l.append(lst[i])
    return l

Since i never changes, your code keeps adding lst[0] to l forever.

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    i = 0
    while i < len(lst):
        l.append(lst[i])
        i += 1
    return l

Now your while loop will iterate through the list properly. Let's inspect what is happening in the while loop with i now. It starts at 0 and is incremented by 1 until it is not less than len(lst) anymore. Another way to write this is with a for loop (for i in range(0, len(lst), 1):). In this syntax, i starts at 0, and exits the loop when it is greater than or equal to len(lst) and increments by 1.

#filling l with items of lst with a while loop
def foo2(lst):
    l = []
    for i in range(0, len(lst), 1):
        l.append(lst[i])
    return l

Now this can be rewritten as a list comprehension:

#filling l with items of lst with a while loop
def foo2(lst):
    return [lst[i] for i in range(0, len(lst), 1)]

For loops and while loops can accomplish the same task, but it's important to think about which type of loop is more appropriate for the task. For loops are great for tasks where we know how many iterations we want and while loops are great for when we don't know how many times to run the loop. For your foo2 function, it was clear that we wanted to iterate through each item in the list, so a for loop is most appropriate. We are then able to transform that into a list comprehension (a) because the language's syntax allows for it and (b) because list comprehensions are also a structure that is best used when the number of iterations is clear, like in a 1-to-1 relationship. In the case of your integer_factorization(x) function, the use of for loops and while loops seems to be appropriate. You use a for loop to iterate through the finite list of numbers returned by sieve_eratosthenes(x) and then use a while loop to add number to a list ~while~ a certain condition is true.

Hayley Guillou
  • 3,953
  • 4
  • 24
  • 34
  • Oh yea obviously I need to increment i in foo2(), but that was clear to me (I wrote the code in a rush so I kinda forgot to add this line) The main "problem" for me was to understand why python don't allow to use while-loops in list-comprehensions. But as you stated while-loops are not guaranteed to terminate, so that makes sense – IPiiro Nov 26 '20 at 10:44