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