Tim Chase wrote:
If you want to literally remove None objects from a list....(or mutable sequence)

def deNone(alist):
   n=len(alist)
   i=j=0
   while i < n:
     if alist[i] is not None:
       alist[j] = alist[i]
       j += 1
     i += 1
   alist[j:i] = []

blist=[None,1,None,2,None,3,None,None,4,None]
deNone(blist)
print(blist)

# prints [1, 2, 3, 4]

...wouldn't a cleaner way of doing this just be

  >>> blist=[None,1,None,2,None,3,None,None,4,None]

No, making a filtered copy that is then copied back before being deleted is algorithmically much messier. My code does the minimum work necessary and is algorithmically cleaner.

  >>> alist = blist
  >>> blist[:] = [x for x in blist if x is not None]
  >>> blist
  [1, 2, 3, 4]
  >>> alist
  [1, 2, 3, 4]

By using the slice assignment, it leaves the blist referring to the same list-object (as shown by the "alist" bit), and modifying it in place. This reads a lot more cleanly in my estimation.

If the data-set is large, in 2.5+, you can just use a generator:

  blist[:] = (x for x in blist if x is not None)

Given that this works, that the setup for slice assignment does not mess up the co-routine iteration over the same loop, this is pretty good. It amounts to deNone with the i-j loop separated into an i loop and a j loop in source and consumer co-routines. One could argue that that is even better, even if written out as

def deNone2(alist):
  src = (item for item in alist if item is not None)
  j=0
  try:
    while True:
      alist[j] = next(src)
      j += 1
  except StopIteration:
    pass
  alist[j:] = []

tjr

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to