#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    32
    Rep Power
    3

    Iterators and generators.


    I have this generator:

    PHP Code:
    def takeOnly(it,pred,f):
        
    count 0
        
    for i in it:
            if 
    not count == f:
                if 
    pred(i):
                    
    count 0
                    yield i
                
    else:
                    
    count += 1
            
    else:
                break 
    it receives an iterator, a predicate and a limit "f". The generator will yield all the items that meet the requirement of the predicate. As soon as "f" consecutive items in the iterator don't meet the requirement, the operation is terminated.

    the generator works fine but I noticed that it has a little problem handling "infinite" iterators (the generator in this case doesn't stop, the memory is filled and the python shell crashes). How can I take care of this issue?
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,966
    Rep Power
    481
    please show failure, works fine in python3 for several test cases.
    Code:
    >>> def takeOnly(it,pred,f):
        count = 0
        for i in it:
            if not count == f:
                if pred(i):
                    count = 0
                    yield i
                else:
                    count += 1
            else:
                break
    
    def odd(a):
        return a & 1
    
    ... ... ... ... ... ... ... ... ... ... ... >>> ... ... >>> 
    >>> for i in takeOnly([1,2,3,4,5,6,6,6,6,6],odd,3):
    ...  print(i)
    ... 
    1
    3
    5
    >>> for i in takeOnly([1,2,2,2,2,3,4,5,6,6,6,6,6],odd,3):
    ...  print(i)
    ... 
    1
    >>> for i in takeOnly([1,2,3],odd,8):
    ...  print(i)
    ... 
    1
    3
    >>> for i in takeOnly(itertools.repeat(1),odd,8):
    ...  print(i)
    ... 
    1   (many 1's removed)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in takeOnly
    KeyboardInterrupt
    >>>
    [code]Code tags[/code] are essential for python code and Makefiles!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    32
    Rep Power
    3
    Originally Posted by b49P23TIvg
    please show failure, works fine in python3 for several test cases.
    Code:
    >>> def takeOnly(it,pred,f):
        count = 0
        for i in it:
            if not count == f:
                if pred(i):
                    count = 0
                    yield i
                else:
                    count += 1
            else:
                break
    
    def odd(a):
        return a & 1
    
    ... ... ... ... ... ... ... ... ... ... ... >>> ... ... >>> 
    >>> for i in takeOnly([1,2,3,4,5,6,6,6,6,6],odd,3):
    ...  print(i)
    ... 
    1
    3
    5
    >>> for i in takeOnly([1,2,2,2,2,3,4,5,6,6,6,6,6],odd,3):
    ...  print(i)
    ... 
    1
    >>> for i in takeOnly([1,2,3],odd,8):
    ...  print(i)
    ... 
    1
    3
    >>> for i in takeOnly(itertools.repeat(1),odd,8):
    ...  print(i)
    ... 
    1   (many 1's removed)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 4, in takeOnly
    KeyboardInterrupt
    >>>
    Yes, take the last test you tried for example. That's exactly where my program gets stuck, I need to find an appropriate halting condition that blocks it from entering in an infinite loop. As I noticed, you too had to stop it with a keyboardInterrupt order. Rather, I would like to raise a StopIteration to exit the loop. How could this be done so it can work with "any" infinite iterator?
  6. #4
  7. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,966
    Rep Power
    481

    use another argument


    Code:
    def takeOnly(it,pred,f,at_most=8888888888):
        count = 0
        yielded = 0
        for i in it:
            if (count < f) and (yielded < at_most):
                if pred(i):
                    count = 0
                    yielded += 1
                    yield i
                else:
                    count += 1
            else:
                break
    
    def odd(a):
        return a & 1
    
    
    import itertools
    
    for i in takeOnly(itertools.repeat(1),odd,8,at_most=20):
        print(i)
    [code]Code tags[/code] are essential for python code and Makefiles!

IMN logo majestic logo threadwatch logo seochat tools logo