def __setitem__(self, key, value): try: i, j = key except (ValueError, TypeError): raise TypeError("index must be a pair of integers or slices") # First deal with the case where both i and j are integers if isintlike(i) and isintlike(j): if i < 0: i += self.shape[0] if j < 0: j += self.shape[1] if i < 0 or i >= self.shape[0] or j < 0 or j >= self.shape[1]: raise IndexError("index out of bounds") if np.isscalar(value): if value == 0: if self.has_key((i,j)): del self[(i,j)] else: dict.__setitem__(self, (i,j), self.dtype.type(value)) else: raise ValueError('setting an array element with a sequence') else: # Either i or j is a slice, sequence, or invalid. If i is a slice # or sequence, unfold it first and call __setitem__ recursively. if isinstance(i, slice): # Is there an easier way to do this? seq = xrange(i.start or 0, i.stop or self.shape[0], i.step or 1) elif _is_sequence(i): seq = i else: # Make sure i is an integer. (But allow it to be a subclass of int). if not isintlike(i): raise TypeError("index must be a pair of integers or slices") seq = None if seq is not None: # First see if 'value' is another dok_matrix of the appropriate # dimensions if isinstance(value, dok_matrix): if value.shape[1] == 1: for element in seq: self[element, j] = value[element, 0] else: raise NotImplementedError("setting a 2-d slice of" " a dok_matrix is not yet supported") elif np.isscalar(value): for element in seq: self[element, j] = value else: # See if value is a sequence try: if len(seq) != len(value): raise ValueError("index and value ranges must" " have the same length") except TypeError: # Not a sequence raise TypeError("unsupported type for" " dok_matrix.__setitem__") # Value is a sequence for element, val in izip(seq, value): self[element, j] = val # don't use dict.__setitem__ # here, since we still want to be able to delete # 0-valued keys, do type checking on 'val' (e.g. if # it's a rank-1 dense array), etc. else: # Process j if isinstance(j, slice): seq = xrange(j.start or 0, j.stop or self.shape[1], j.step or 1) elif _is_sequence(j): seq = j else: # j is not an integer raise TypeError("index must be a pair of integers or slices") # First see if 'value' is another dok_matrix of the appropriate # dimensions if isinstance(value, dok_matrix): if value.shape[0] == 1: for element in seq: self[i, element] = value[0, element] else: raise NotImplementedError("setting a 2-d slice of" " a dok_matrix is not yet supported") elif np.isscalar(value): for element in seq: self[i, element] = value else: # See if value is a sequence try: if len(seq) != len(value): raise ValueError("index and value ranges must have" " the same length") except TypeError: # Not a sequence raise TypeError("unsupported type for dok_matrix.__setitem__") else: for element, val in izip(seq, value): self[i, element] = val
def __setitem__(self, key, value): try: i, j = key except (ValueError, TypeError): raise TypeError("index must be a pair of integers or slices") # First deal with the case where both i and j are integers if isintlike(i) and isintlike(j): if i < 0: i += self.shape[0] if j < 0: j += self.shape[1] if i < 0 or i >= self.shape[0] or j < 0 or j >= self.shape[1]: raise IndexError("index out of bounds") if np.isscalar(value): if value == 0: if self.has_key((i, j)): del self[(i, j)] else: dict.__setitem__(self, (i, j), self.dtype.type(value)) else: raise ValueError('setting an array element with a sequence') else: # Either i or j is a slice, sequence, or invalid. If i is a slice # or sequence, unfold it first and call __setitem__ recursively. if isinstance(i, slice): # Is there an easier way to do this? seq = xrange(i.start or 0, i.stop or self.shape[0], i.step or 1) elif _is_sequence(i): seq = i else: # Make sure i is an integer. (But allow it to be a subclass of int). if not isintlike(i): raise TypeError( "index must be a pair of integers or slices") seq = None if seq is not None: # First see if 'value' is another dok_matrix of the appropriate # dimensions if isinstance(value, dok_matrix): if value.shape[1] == 1: for element in seq: self[element, j] = value[element, 0] else: raise NotImplementedError( "setting a 2-d slice of" " a dok_matrix is not yet supported") elif np.isscalar(value): for element in seq: self[element, j] = value else: # See if value is a sequence try: if len(seq) != len(value): raise ValueError("index and value ranges must" " have the same length") except TypeError: # Not a sequence raise TypeError("unsupported type for" " dok_matrix.__setitem__") # Value is a sequence for element, val in izip(seq, value): self[element, j] = val # don't use dict.__setitem__ # here, since we still want to be able to delete # 0-valued keys, do type checking on 'val' (e.g. if # it's a rank-1 dense array), etc. else: # Process j if isinstance(j, slice): seq = xrange(j.start or 0, j.stop or self.shape[1], j.step or 1) elif _is_sequence(j): seq = j else: # j is not an integer raise TypeError( "index must be a pair of integers or slices") # First see if 'value' is another dok_matrix of the appropriate # dimensions if isinstance(value, dok_matrix): if value.shape[0] == 1: for element in seq: self[i, element] = value[0, element] else: raise NotImplementedError( "setting a 2-d slice of" " a dok_matrix is not yet supported") elif np.isscalar(value): for element in seq: self[i, element] = value else: # See if value is a sequence try: if len(seq) != len(value): raise ValueError("index and value ranges must have" " the same length") except TypeError: # Not a sequence raise TypeError( "unsupported type for dok_matrix.__setitem__") else: for element, val in izip(seq, value): self[i, element] = val
def __getitem__(self, key): """If key=(i,j) is a pair of integers, return the corresponding element. If either i or j is a slice or sequence, return a new sparse matrix with just these elements. """ try: i, j = key except (ValueError, TypeError): raise TypeError('index must be a pair of integers or slices') # Bounds checking if isintlike(i): if i < 0: i += self.shape[0] if i < 0 or i >= self.shape[0]: raise IndexError('index out of bounds') if isintlike(j): if j < 0: j += self.shape[1] if j < 0 or j >= self.shape[1]: raise IndexError('index out of bounds') # First deal with the case where both i and j are integers if isintlike(i) and isintlike(j): return dict.get(self, (i,j), 0.) else: # Either i or j is a slice, sequence, or invalid. If i is a slice # or sequence, unfold it first and call __getitem__ recursively. if isinstance(i, slice): # Is there an easier way to do this? seq = xrange(i.start or 0, i.stop or self.shape[0], i.step or 1) elif _is_sequence(i): seq = i else: # Make sure i is an integer. (But allow it to be a subclass of int). if not isintlike(i): raise TypeError('index must be a pair of integers or slices') seq = None if seq is not None: # i is a seq if isintlike(j): # Create a new matrix of the correct dimensions first = seq[0] last = seq[-1] if first < 0 or first >= self.shape[0] or last < 0 \ or last >= self.shape[0]: raise IndexError('index out of bounds') newshape = (last-first+1, 1) new = dok_matrix(newshape) # ** This uses linear time in the size m of dimension 0: # new[0:seq[-1]-seq[0]+1, 0] = \ # [self.get((element, j), 0) for element in seq] # ** Instead just add the non-zero elements. This uses # ** linear time in the number of non-zeros: for (ii, jj) in self.keys(): if jj == j and ii >= first and ii <= last: dict.__setitem__(new, (ii-first, 0), \ dict.__getitem__(self, (ii,jj))) else: ################################### # We should reshape the new matrix here! ################################### raise NotImplementedError("fancy indexing supported over" " one axis only") return new # Below here, j is a sequence, but i is an integer if isinstance(j, slice): # Is there an easier way to do this? seq = xrange(j.start or 0, j.stop or self.shape[1], j.step or 1) elif _is_sequence(j): seq = j else: # j is not an integer raise TypeError("index must be a pair of integers or slices") # Create a new matrix of the correct dimensions first = seq[0] last = seq[-1] if first < 0 or first >= self.shape[1] or last < 0 \ or last >= self.shape[1]: raise IndexError("index out of bounds") newshape = (1, last-first+1) new = dok_matrix(newshape) # ** This uses linear time in the size n of dimension 1: # new[0, 0:seq[-1]-seq[0]+1] = \ # [self.get((i, element), 0) for element in seq] # ** Instead loop over the non-zero elements. This is slower # ** if there are many non-zeros for (ii, jj) in self.keys(): if ii == i and jj >= first and jj <= last: dict.__setitem__(new, (0, jj-first), \ dict.__getitem__(self, (ii,jj))) return new
def __getitem__(self, key): """If key=(i,j) is a pair of integers, return the corresponding element. If either i or j is a slice or sequence, return a new sparse matrix with just these elements. """ try: i, j = key except (ValueError, TypeError): raise TypeError('index must be a pair of integers or slices') # Bounds checking if isintlike(i): if i < 0: i += self.shape[0] if i < 0 or i >= self.shape[0]: raise IndexError('index out of bounds') if isintlike(j): if j < 0: j += self.shape[1] if j < 0 or j >= self.shape[1]: raise IndexError('index out of bounds') # First deal with the case where both i and j are integers if isintlike(i) and isintlike(j): return dict.get(self, (i, j), 0.) else: # Either i or j is a slice, sequence, or invalid. If i is a slice # or sequence, unfold it first and call __getitem__ recursively. if isinstance(i, slice): # Is there an easier way to do this? seq = xrange(i.start or 0, i.stop or self.shape[0], i.step or 1) elif _is_sequence(i): seq = i else: # Make sure i is an integer. (But allow it to be a subclass of int). if not isintlike(i): raise TypeError( 'index must be a pair of integers or slices') seq = None if seq is not None: # i is a seq if isintlike(j): # Create a new matrix of the correct dimensions first = seq[0] last = seq[-1] if first < 0 or first >= self.shape[0] or last < 0 \ or last >= self.shape[0]: raise IndexError('index out of bounds') newshape = (last - first + 1, 1) new = dok_matrix(newshape) # ** This uses linear time in the size m of dimension 0: # new[0:seq[-1]-seq[0]+1, 0] = \ # [self.get((element, j), 0) for element in seq] # ** Instead just add the non-zero elements. This uses # ** linear time in the number of non-zeros: for (ii, jj) in self.keys(): if jj == j and ii >= first and ii <= last: dict.__setitem__(new, (ii-first, 0), \ dict.__getitem__(self, (ii,jj))) else: ################################### # We should reshape the new matrix here! ################################### raise NotImplementedError("fancy indexing supported over" " one axis only") return new # Below here, j is a sequence, but i is an integer if isinstance(j, slice): # Is there an easier way to do this? seq = xrange(j.start or 0, j.stop or self.shape[1], j.step or 1) elif _is_sequence(j): seq = j else: # j is not an integer raise TypeError("index must be a pair of integers or slices") # Create a new matrix of the correct dimensions first = seq[0] last = seq[-1] if first < 0 or first >= self.shape[1] or last < 0 \ or last >= self.shape[1]: raise IndexError("index out of bounds") newshape = (1, last - first + 1) new = dok_matrix(newshape) # ** This uses linear time in the size n of dimension 1: # new[0, 0:seq[-1]-seq[0]+1] = \ # [self.get((i, element), 0) for element in seq] # ** Instead loop over the non-zero elements. This is slower # ** if there are many non-zeros for (ii, jj) in self.keys(): if ii == i and jj >= first and jj <= last: dict.__setitem__(new, (0, jj-first), \ dict.__getitem__(self, (ii,jj))) return new