@@ -6,12 +6,35 @@ import { DimensionError } from '../../error/DimensionError.js'
66import { factory } from '../../utils/factory.js'
77
88const name = 'subset'
9- const dependencies = [ 'typed' , 'matrix' , 'zeros' , 'add' ]
9+ export const dependencies = [ 'typed' , 'matrix' , 'zeros' , 'add' , 'index' , 'size ']
1010
11- export const createSubset = /* #__PURE__ */ factory ( name , dependencies , ( { typed, matrix, zeros, add } ) => {
11+ export const createSubset = /* #__PURE__ */ factory ( name , dependencies , ( { typed, matrix, zeros, add, index , size } ) => {
1212 /**
1313 * Get or set a subset of a matrix or string.
1414 *
15+ * The second argument should be a specification of the desired subset of
16+ * the first argument. Therefore, the second argument is typically an Index
17+ * object produced by the `index` function, which see (in short, for each
18+ * dimension of the matrix, the Index specifies one position or a list or
19+ * range of positions to include in the subset).
20+ *
21+ * For convenience, the second argument may be simply a number n, in which
22+ * case the subset is the entire section of one dimension lower than the
23+ * given matrix, at position n. In other words, it corresponds to the
24+ * entry of a vector at position n, or the row of a 2D matrix at position
25+ * n, etc.
26+ *
27+ * Furthermore, it can also be an array of appropriate arguments to the
28+ * `index` function, in which case it will be passed to the `index` function
29+ * for you. Beware, though: in the case of a 1d vector v,
30+ * `math.subset(v, [2, 3])` will not therefore return the elements at
31+ * positions 2 and 3, because passing those arguments to `index` would
32+ * attempt to index the first dimension of v by and its nonexistent second
33+ * dimension by 3. You can call `math.subset(v, [[2, 3]])` to obtain the
34+ * elements at positions 2 and 3, because now the inner `[2, 3]` will be
35+ * interpreted as the list of positions with which to index into the first
36+ * dimension.
37+ *
1538 * Syntax:
1639 * math.subset(value, index) // retrieve a subset
1740 * math.subset(value, index, replacement [, defaultValue]) // replace a subset
@@ -20,23 +43,29 @@ export const createSubset = /* #__PURE__ */ factory(name, dependencies, ({ typed
2043 *
2144 * // get a subset
2245 * const d = [[1, 2], [3, 4]]
23- * math.subset(d, math.index(1, 0)) // returns 3
24- * math.subset(d, math.index([0, 1], [1])) // returns [[2], [4]]
25- * math.subset(d, math.index([false, true], [0])) // returns [[3]]
46+ * math.subset(d, math.index(1, 0)) // returns 3 ...
47+ * math.subset(d, [1, 0]) // returns 3 ...
48+ * math.subset(d, math.index([0, 1], [1])) // Array [[2], [4]] ...
49+ * math.subset(d, [[0, 1], [1]]) // Array [[2], [4]] ...
50+ * math.subset(d, math.index([false, true], [0])) // Array [[3]] ...
51+ * math.subset(d, [[false, true], 0]) // Array [3] ...
52+ * math.subset(d, 1) // Array [3, 4]
2653 *
2754 * // replace a subset
2855 * const e = []
29- * const f = math.subset(e, math.index(0, [0, 2]), [5, 6]) // f = [[5, 0, 6]]
30- * const g = math.subset(f, math.index(1, 1), 7, 0) // g = [[5, 0, 6], [0, 7, 0]]
31- * math.subset(g, math.index([false, true], 1), 8) // returns [[5, 0, 6], [0, 8, 0]]
56+ * const f = math.subset(e, math.index(0, [0, 2]), [5, 6])
57+ * f // Array [[5, 0, 6]] ...
58+ * const g = math.subset(f, math.index(1, 1), 7, 0)
59+ * g // Array [[5, 0, 6], [0, 7, 0]] ...
60+ * math.subset(g, math.index([false, true], 1), 8) // Array [[5, 0, 6], [0, 8, 0]]
3261 *
3362 * // get submatrix using ranges
3463 * const M = [
3564 * [1, 2, 3],
3665 * [4, 5, 6],
3766 * [7, 8, 9]
3867 * ]
39- * math.subset(M, math.index(math.range(0,2), math.range(0,3))) // [[1, 2, 3], [4, 5, 6]]
68+ * math.subset(M, math.index(math.range(0,2), math.range(0,3))) // Array [[1, 2, 3], [4, 5, 6]]
4069 *
4170 * See also:
4271 *
@@ -75,6 +104,23 @@ export const createSubset = /* #__PURE__ */ factory(name, dependencies, ({ typed
75104
76105 'string, Index' : _getSubstring ,
77106
107+ // Allow single number index to get layer:
108+ 'Matrix, number' : function ( M , position ) {
109+ return M . layer ( position )
110+ } ,
111+
112+ 'Array, number' : function ( A , position ) {
113+ return A [ position ]
114+ } ,
115+
116+ 'string, number' : function ( s , position ) {
117+ return s . charAt ( position )
118+ } ,
119+
120+ // Otherwise pass second array argument to index function for convenience
121+ 'Matrix | Array | Object | string, Array' : typed . referToSelf (
122+ self => ( v , i ) => self ( v , index ( ...i ) ) ) ,
123+
78124 // set subset
79125 'Matrix, Index, any, any' : function ( value , index , replacement , defaultValue ) {
80126 if ( isEmptyIndex ( index ) ) { return value }
@@ -89,19 +135,31 @@ export const createSubset = /* #__PURE__ */ factory(name, dependencies, ({ typed
89135 }
90136 } ) ,
91137
92- 'Array, Index, any' : typed . referTo ( 'Matrix, Index, any, any' , function ( subsetRef ) {
93- return function ( value , index , replacement ) {
94- return subsetRef ( matrix ( value ) , index , replacement , undefined ) . valueOf ( )
95- }
96- } ) ,
97-
98- 'Matrix, Index, any' : typed . referTo ( 'Matrix, Index, any, any' , function ( subsetRef ) {
99- return function ( value , index , replacement ) { return subsetRef ( value , index , replacement , undefined ) }
100- } ) ,
101-
102138 'string, Index, string' : _setSubstring ,
103139 'string, Index, string, string' : _setSubstring ,
104- 'Object, Index, any' : _setObjectProperty
140+ 'Object, Index, any' : _setObjectProperty ,
141+
142+ // fourth argument defaults to undefined:
143+ 'Matrix | Array, Index | Array | number, any' : typed . referToSelf (
144+ self => ( v , pos , rep ) => self ( v , pos , rep , undefined )
145+ ) ,
146+
147+ // Allow 2nd index to be a number:
148+ 'Matrix | Array | Object | string, number, any, any' : typed . referToSelf (
149+ self => ( v , pos , rep , def ) => {
150+ const ix = [ pos ]
151+ let wildcards = size ( v ) . length
152+ while ( -- wildcards > 0 ) ix . push ( ':' )
153+ return self ( v , index ( ...ix ) , rep , def )
154+ } ) ,
155+
156+ 'string, number, string' : typed . referTo (
157+ 'string, Index, string' , sis => ( s , n , rep ) => sis ( s , index ( n ) , rep ) ) ,
158+
159+ // Or allow 2nd argument to be an array of arguments to index
160+ 'Matrix | Array | Object | string, Array, any, any' : typed . referToSelf (
161+ self => ( v , ixes , rep , def ) => self ( v , index ( ...ixes ) , rep , def )
162+ )
105163 } )
106164
107165 /**
0 commit comments