simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

subset.js (7347B)


      1 import { isIndex } from '../../utils/is.js';
      2 import { clone } from '../../utils/object.js';
      3 import { validateIndex } from '../../utils/array.js';
      4 import { getSafeProperty, setSafeProperty } from '../../utils/customs.js';
      5 import { DimensionError } from '../../error/DimensionError.js';
      6 import { factory } from '../../utils/factory.js';
      7 var name = 'subset';
      8 var dependencies = ['typed', 'matrix'];
      9 export var createSubset = /* #__PURE__ */factory(name, dependencies, _ref => {
     10   var {
     11     typed,
     12     matrix
     13   } = _ref;
     14 
     15   /**
     16    * Get or set a subset of a matrix or string.
     17    *
     18    * Syntax:
     19    *     math.subset(value, index)                                // retrieve a subset
     20    *     math.subset(value, index, replacement [, defaultValue])  // replace a subset
     21    *
     22    * Examples:
     23    *
     24    *     // get a subset
     25    *     const d = [[1, 2], [3, 4]]
     26    *     math.subset(d, math.index(1, 0))        // returns 3
     27    *     math.subset(d, math.index([0, 1], 1))   // returns [[2], [4]]
     28    *
     29    *     // replace a subset
     30    *     const e = []
     31    *     const f = math.subset(e, math.index(0, [0, 2]), [5, 6])  // f = [[5, 6]] and e = [[5, 0, 6]]
     32    *     const g = math.subset(f, math.index(1, 1), 7, 0)         // g = [[5, 6], [0, 7]]
     33    *
     34    *     // get submatrix using ranges
     35    *     const M = [
     36    *       [1,2,3],
     37    *       [4,5,6],
     38    *       [7,8,9]
     39    *     ]
     40    *     math.subset(M, math.index(math.range(0,2), math.range(0,3))) // [[1,2,3],[4,5,6]]
     41    *
     42    * See also:
     43    *
     44    *     size, resize, squeeze, index
     45    *
     46    * @param {Array | Matrix | string} matrix  An array, matrix, or string
     47    * @param {Index} index
     48    *    For each dimension of the target, specifies an index or a list of
     49    *    indices to fetch or set. `subset` uses the cartesian product of
     50    *    the indices specified in each dimension.
     51    * @param {*} [replacement]                 An array, matrix, or scalar.
     52    *                                          If provided, the subset is replaced with replacement.
     53    *                                          If not provided, the subset is returned
     54    * @param {*} [defaultValue=undefined]      Default value, filled in on new entries when
     55    *                                          the matrix is resized. If not provided,
     56    *                                          math.matrix elements will be left undefined.
     57    * @return {Array | Matrix | string} Either the retrieved subset or the updated matrix.
     58    */
     59   return typed(name, {
     60     // get subset
     61     'Array, Index': function ArrayIndex(value, index) {
     62       var m = matrix(value);
     63       var subset = m.subset(index); // returns a Matrix
     64 
     65       return index.isScalar() ? subset : subset.valueOf(); // return an Array (like the input)
     66     },
     67     'Matrix, Index': function MatrixIndex(value, index) {
     68       return value.subset(index);
     69     },
     70     'Object, Index': _getObjectProperty,
     71     'string, Index': _getSubstring,
     72     // set subset
     73     'Array, Index, any': function ArrayIndexAny(value, index, replacement) {
     74       return matrix(clone(value)).subset(index, replacement, undefined).valueOf();
     75     },
     76     'Array, Index, any, any': function ArrayIndexAnyAny(value, index, replacement, defaultValue) {
     77       return matrix(clone(value)).subset(index, replacement, defaultValue).valueOf();
     78     },
     79     'Matrix, Index, any': function MatrixIndexAny(value, index, replacement) {
     80       return value.clone().subset(index, replacement);
     81     },
     82     'Matrix, Index, any, any': function MatrixIndexAnyAny(value, index, replacement, defaultValue) {
     83       return value.clone().subset(index, replacement, defaultValue);
     84     },
     85     'string, Index, string': _setSubstring,
     86     'string, Index, string, string': _setSubstring,
     87     'Object, Index, any': _setObjectProperty
     88   });
     89 });
     90 /**
     91  * Retrieve a subset of a string
     92  * @param {string} str            string from which to get a substring
     93  * @param {Index} index           An index or list of indices (character positions)
     94  * @returns {string} substring
     95  * @private
     96  */
     97 
     98 function _getSubstring(str, index) {
     99   if (!isIndex(index)) {
    100     // TODO: better error message
    101     throw new TypeError('Index expected');
    102   }
    103 
    104   if (index.size().length !== 1) {
    105     throw new DimensionError(index.size().length, 1);
    106   } // validate whether the range is out of range
    107 
    108 
    109   var strLen = str.length;
    110   validateIndex(index.min()[0], strLen);
    111   validateIndex(index.max()[0], strLen);
    112   var range = index.dimension(0);
    113   var substr = '';
    114   range.forEach(function (v) {
    115     substr += str.charAt(v);
    116   });
    117   return substr;
    118 }
    119 /**
    120  * Replace a substring in a string
    121  * @param {string} str            string to be replaced
    122  * @param {Index} index           An index or list of indices (character positions)
    123  * @param {string} replacement    Replacement string
    124  * @param {string} [defaultValue] Default value to be uses when resizing
    125  *                                the string. is ' ' by default
    126  * @returns {string} result
    127  * @private
    128  */
    129 
    130 
    131 function _setSubstring(str, index, replacement, defaultValue) {
    132   if (!index || index.isIndex !== true) {
    133     // TODO: better error message
    134     throw new TypeError('Index expected');
    135   }
    136 
    137   if (index.size().length !== 1) {
    138     throw new DimensionError(index.size().length, 1);
    139   }
    140 
    141   if (defaultValue !== undefined) {
    142     if (typeof defaultValue !== 'string' || defaultValue.length !== 1) {
    143       throw new TypeError('Single character expected as defaultValue');
    144     }
    145   } else {
    146     defaultValue = ' ';
    147   }
    148 
    149   var range = index.dimension(0);
    150   var len = range.size()[0];
    151 
    152   if (len !== replacement.length) {
    153     throw new DimensionError(range.size()[0], replacement.length);
    154   } // validate whether the range is out of range
    155 
    156 
    157   var strLen = str.length;
    158   validateIndex(index.min()[0]);
    159   validateIndex(index.max()[0]); // copy the string into an array with characters
    160 
    161   var chars = [];
    162 
    163   for (var i = 0; i < strLen; i++) {
    164     chars[i] = str.charAt(i);
    165   }
    166 
    167   range.forEach(function (v, i) {
    168     chars[v] = replacement.charAt(i[0]);
    169   }); // initialize undefined characters with a space
    170 
    171   if (chars.length > strLen) {
    172     for (var _i = strLen - 1, _len = chars.length; _i < _len; _i++) {
    173       if (!chars[_i]) {
    174         chars[_i] = defaultValue;
    175       }
    176     }
    177   }
    178 
    179   return chars.join('');
    180 }
    181 /**
    182  * Retrieve a property from an object
    183  * @param {Object} object
    184  * @param {Index} index
    185  * @return {*} Returns the value of the property
    186  * @private
    187  */
    188 
    189 
    190 function _getObjectProperty(object, index) {
    191   if (index.size().length !== 1) {
    192     throw new DimensionError(index.size(), 1);
    193   }
    194 
    195   var key = index.dimension(0);
    196 
    197   if (typeof key !== 'string') {
    198     throw new TypeError('String expected as index to retrieve an object property');
    199   }
    200 
    201   return getSafeProperty(object, key);
    202 }
    203 /**
    204  * Set a property on an object
    205  * @param {Object} object
    206  * @param {Index} index
    207  * @param {*} replacement
    208  * @return {*} Returns the updated object
    209  * @private
    210  */
    211 
    212 
    213 function _setObjectProperty(object, index, replacement) {
    214   if (index.size().length !== 1) {
    215     throw new DimensionError(index.size(), 1);
    216   }
    217 
    218   var key = index.dimension(0);
    219 
    220   if (typeof key !== 'string') {
    221     throw new TypeError('String expected as index to retrieve an object property');
    222   } // clone the object, and apply the property to the clone
    223 
    224 
    225   var updated = clone(object);
    226   setSafeProperty(updated, key, replacement);
    227   return updated;
    228 }