-2

Is there a way to use a while loop in a list comprehension.

For example, I have a single line Fibonacci generator:

[int(((1+(5**0.5))**n-(1-(5**0.5))**n)/(2**n*(5**0.5))) for n in range(100)]

but I'd like it to stop at a certain outcome, rather than just run a certain number of times. (i.e. all Fibonacci sequence numbers below 4,000,000)

This is a question about list-comprehension, not about lists in general.

The more generic phrasing might be this:

[(formula using incrementing variable) 
    for incrementing variable while (result is less than specified amount)]
Sanjurjo7
  • 17
  • 1
  • 6
  • Have a look at this answer: http://stackoverflow.com/questions/31003486/stopping-list-selection-in-python-2-7 – Hunter McMillen Jan 18 '17 at 15:26
  • Yes, there's a way. Have you even tried to write the `while` loop? – blacksite Jan 18 '17 at 15:26
  • 2
    You can use a generator expression instead of a list comprehension, and then loop over it until some point, or use `itertools.takewhile()`. – Sven Marnach Jan 18 '17 at 15:27
  • 1
    That said, using the explicit formula for the Fibonacci numbers is completely pointless if you want to generate them one by one anyway. Just use the recursion relation in a while loop. – Sven Marnach Jan 18 '17 at 15:27
  • 1
    The point isn't to complete the desired exercise, but rather to ask if there is a way to nest the while loop into the list comprehension. I get that you can do this with a lambda, I'm just wondering if a while statement can be placed in this phrasing. I've tried it a couple of different ways and keep getting syntax errors based on the while. – Sanjurjo7 Jan 18 '17 at 15:36
  • I reopened the question because the solution to the linked duplicate question does not address the issue here since it doesn't _stop_ the computations in the loop, just doesn't store their results in the list produced. – martineau Jan 18 '17 at 16:24
  • Sanjurjo7: What's the point of stopping _before_ the desired result? That seems to imply the desired result _isn't_ really the one desired. Is the resulting list only going to have one element in it? Please [edit] your question and clarify what results are you really want. – martineau Jan 18 '17 at 16:33
  • In the Fibonacci example it would mean, for all numbers in the sequence below 4,000,000. I see what you are saying, clarifying now. – Sanjurjo7 Jan 18 '17 at 16:51

1 Answers1

0

python don't have such feature of using while in a comprehension (which is like a map combined with filter), but you can accomplished that using other tools like making a function that do what you desire or using your best friend the itertools module. For example

example 1, with itertools

>>> from itertools import takewhile
>>> def fib():
        fk,fk1 = 0,1
        while True:
            yield fk
            fk, fk1 = fk1, fk + fk1


>>> list(takewhile(lambda fn:fn<100,fib()))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> 

example 2, with a function

>>> def fib_while(tope):
        fk,fk1 = 0,1
        while fk < tope:
            yield fk
            fk,fk1 = fk1, fk + fk1


>>> list(fib_while(100))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>>    

oh, I forgot to mention, but your formula for getting the Fibonacci numbers, even if mathematical correct, is doom to fail to get the real value for a large enough n, because floating point arithmetic rounding errors

the point of divergence is very easy to found (using the above fib)

>>> def fib_float(n):
        return int(((1+(5**0.5))**n-(1-(5**0.5))**n)/(2**n*(5**0.5)))

>>> [n for n,f in zip(range(100),fib()) if f!=fib_float(n)] )
[72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
>>>

so for all n>=72 what you get are not Fibonacci numbers...

if you only care for all numbers in the sequence below 4,000,000 then that is not a problem of course as the limit is n=33

Community
  • 1
  • 1
Copperfield
  • 8,131
  • 3
  • 23
  • 29
  • Yeah, I ran that range and realized that problem as well. Thanks for the considered response. This is the answer I was looking for, that a list comprehension isn't going to be useful in any case looking for a function to stop when a certain result comes up. – Sanjurjo7 Jan 20 '17 at 17:26