On Tue, 20 May 2008 10:40:17 -0500
"David C. Ullrich" <[EMAIL PROTECTED]> wrote:

> > > Today's little joke: Long ago I would have solved
> > > this by storing the data as a list of rows and _also_
> > > a list of columns, updating each one any time the
> > > other changed. Just goes to show you things
> > > could always be worse...
> > 
> > Well have I ever ... I only thought about this last week and I
> > actually thought it was a *good* idea. 
> 
> Sorry. If you really want to do this you could keep things
> in sync automatically by writing the appropriate __setitem__
> and resolving never to modify the data except through that...
> 
> def whatever.__setitem__(self, (row,col), value):
>   self.rows[row][col] = value
>   self.cols[col][row] = value
 
Using the trick of encapsulating the values inside single-element lists
one can make a transposition of the matrix and get synchronicity for
the little price of doubling the number of instances. Since the views
share the data this is a lot less expensive than one would think. One
can use the row view or the column view to alter data and the changes
will automatically be visible in the other view, since the views update
the same lists. There is a little notational gotcha, instead of writing
row[0] = [1,2,3] one now must write row[0][:] = [1,2,3] or else
synchronicity is lost.

I found a nice ListMixin class at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440656

Using that I wrote the following proof of concept:

class Storage(ListMixin):

  def __init__(self, seq=[]):
    self.L = [[x] for x in seq] 

  def _constructor(self, iterable):
    return Storage(iterable)

  def __len__(self):
    return len(self.L)

  def _get_element(self, i):
    assert 0 <= i < len(self)
    return self.L[i][0]

  def _set_element(self, i, x):
    assert 0 <= i < len(self)
    self.L[i][0] = x

  def _resize_region(self, start, end, new_size):
    assert 0 <= start <= len(self)
    assert 0 <= end   <= len(self)
    assert start <= end
    self.L[start:end] = [[None] for i in range(new_size)]

def test():
    n = 3
    R = range(n)
    it = iter(range(n*n))
    MR = [Storage(it.next() for i in R) for i in R]
    MC = [Storage() for i in R]
    T = zip(*[x.L for x in MR])
    for x,y in zip(MC,T):
        x.L = y
    print MR
    print MC
    MC[2][:] = 'abc'
    print
    print MR
    print MC
    
if __name__=='__main__':
    test()

Output:

[Storage([0, 1, 2]), Storage([3, 4, 5]), Storage([6, 7, 8])]
[Storage([0, 3, 6]), Storage([1, 4, 7]), Storage([2, 5, 8])]

[Storage([0, 1, 'a']), Storage([3, 4, 'b']), Storage([6, 7, 'c'])]
[Storage([0, 3, 6]), Storage([1, 4, 7]), Storage(['a', 'b', 'c'])]

P.

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

Reply via email to