docs: def _distarray_no_missing(self, xc, xd):
          """Distance array calculation for data with no missing values. The 'pdist() function outputs a condense distance array, and squareform() converts this vector-form
          distance vector to a square-form, redundant distance matrix.
          *This could be a target for saving memory in the future, by not needing to expand to the redundant square-form matrix. """
          from scipy.spatial.distance import pdist, squareform
  
          #------------------------------------------#
          def pre_normalize(x):
              """Normalizes continuous features so they are in the same range (0 to 1)"""
              idx = 0
              # goes through all named features (doesn really need to) this method is only applied to continuous features
              for i in sorted(self.attr.keys()):
                  if self.attr[i][0] == 'discrete':
                      continue
                  cmin = self.attr[i][2]
                  diff = self.attr[i][3]
                  x[:, idx] -= cmin
                  x[:, idx] /= diff
                  idx += 1
              return x
          #------------------------------------------#
  
          if self.data_type == 'discrete':  # discrete features only
              return squareform(pdist(self._X, metric='hamming'))
          elif self.data_type == 'mixed':  # mix of discrete and continuous features
              d_dist = squareform(pdist(xd, metric='hamming'))
              # Cityblock is also known as Manhattan distance
              c_dist = squareform(pdist(pre_normalize(xc), metric='cityblock'))
              return np.add(d_dist, c_dist) / self._num_attributes
  
          else: #continuous features only
              #xc = pre_normalize(xc)
              return squareform(pdist(pre_normalize(xc), metric='cityblock'))