Search code examples
pythongeneratoryield

how to use a generator in python to yield results from dfs?


I have a dfs function (permutation) in which it takes long time to compute all possible values; I wish to create a generator such that every time I call a function get_value it will provide a possible outcome. So in the example below when calling get_value 3 times the results should be:

['1', '2', '3', '4']
['1', '2', '4', '3']

my current execution:

class Solution:
     
 def permutation(self, lst):
 
    if len(lst) == 0:
        return []
  
    if len(lst) == 1:
        return [lst]
  
    l = []
 
    for i in range(len(lst)):
       m = lst[i]
  
       remLst = lst[:i] + lst[i+1:]
       for p in self.permutation(remLst):
           l.append([m] + p)
    return l

 #def get_value():
 #      yield ???

if __name__=='__main__':
    
    s = Solution()
    r = s.permutation(['1','2','3','4']) 

    for p in r:
        print (p)

    #what I want is:
    s = Solution()
    v1 = s.get_value() #['1', '2', '3', '4']
    v2 = s.get_value() #['1', '2', '4', '3']
    #and so forth

Solution

  • For yields in recursion, you can use yield from

        def permutation(self, lst):
    
            if len(lst) == 0:
                return
    
            if len(lst) == 1:
                yield lst
    
            for i in range(len(lst)):
                m = lst[i]
    
                remLst = lst[:i] + lst[i+1:]
                yield from ([m] + p for p in self.permutation(remLst))
    

    The for loop will still work:

    r = s.permutation(['1', '2', '3', '4'])
    for p in r:
        print(p)
    

    Instead of get_value, you should use next():

    r = s.permutation(['1', '2', '3', '4'])
    print(next(r))
    print(next(r))
    print(next(r))
    

    Just be aware that the for loop consumes the iterator:

    r = s.permutation(['1', '2', '3', '4'])
    for p in r:
        print(p)
    r = s.permutation(['1', '2', '3', '4']) # Reset the iterator otherwise `next` will fail
    print(next(r))
    print(next(r))
    print(next(r))