Generator that yields subpatterns of an original pattern with zeros introduced
<p>I have the following problem in which I want to generate patterns with a 0 introduced. The problem is that this should be space efficient, and thus I would like to use a generator that creates and returns one of the patterns at a time (i.e. I do not want to create a list and return it.) I am at a loss here because I don't know what I am doing wrong in calling the generator, so any help would be appreciated!</p>

<p>original pattern = [ 0.  1.  1.  2.]
generator should generate and return these: [ 0.  0.  1.  2.], [0.  1.  0.  2.], [ 0.  1.  1.  0.]</p>

<p>However I can just yield one of the patterns with a call to the generator (the additional 1.0 is not an issue just to not cause any confusion...) and not all of them in succession. </p>

<p>yielded subpattern = (array([ 0.,  1.,  0.,  2.]), 1.0)</p>

<p>The following is my code:</p>

<pre><code>import numpy as np
def removeoneletter(subpattern):
     # generator = []
     originalpattern = subpattern
     subpatterncopy = subpattern.copy()
     nonzero = np.nonzero(subpattern)
     listnonzero = nonzero[0].tolist()
# only replace elements at nonzero positions with zero
     for i in listnonzero:
          subpatterncopy = subpattern.copy()
          position = i
          transaction = subpatterncopy[i]
          np.put(subpatterncopy, position, 0)
          print('subpattern generator')
          print(subpatterncopy)
          # generator.append((subpatterncopy, transaction))
          yield((subpatterncopy, transaction))
          if i == len(listnonzero):
              break
</code></pre>

<p>and the function gets called by another function like so:</p>

<pre><code>def someotherfunction():

  combinations = removeoneletter(subpatterncopy)

  for x in combinations:
       # x = next(combinations)
       print('yielded subpattern')
       print(x)
</code></pre>

<p>Not being an numpy expert, this part looks a bit weird to me:</p>

<pre><code>for i in listnonzero:
    ....
    if i == len(listnonzero):
          break
</code></pre>

<p>Your for loop assigns elements of listnonzero to i, and then you test that against the length of the list. If the listnonzero had five elements [5,42,6,77,12] and the first element you pick from the list happens to be number 5, you would break the loop and exit after the first iteration. </p>

<p>Your code would (probably) work in Javascript or similar where "for i in something" assigns an index to i instead of a list member. </p>

<p>If this does not help, try removing yield and adding a print statement there to see if your listnonzero and i are what you expect them to be. </p>

<p>Just a thought. </p>

<p>Hannu</p>

python generator yield