README.md (7113B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # groupIn 22 23 > Group an object's **own** and **inherited** property values according to an indicator function. 24 25 <!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. --> 26 27 <section class="intro"> 28 29 </section> 30 31 <!-- /.intro --> 32 33 <!-- Package usage documentation. --> 34 35 <section class="usage"> 36 37 ## Usage 38 39 ```javascript 40 var groupIn = require( '@stdlib/utils/group-in' ); 41 ``` 42 43 #### groupIn( obj, \[options,] indicator ) 44 45 Groups an object's **own** and **inherited** property values according to an `indicator` function, which specifies which group a value in the input `object` belongs to. 46 47 ```javascript 48 function indicator( v ) { 49 return v[ 0 ]; 50 } 51 52 function Foo() { 53 this.a = 'beep'; 54 this.b = 'boop'; 55 return this; 56 } 57 58 Foo.prototype = Object.create( null ); 59 Foo.prototype.c = 'foo'; 60 Foo.prototype.d = 'bar'; 61 62 var obj = new Foo(); 63 64 var out = groupIn( obj, indicator ); 65 // e.g., returns { 'b': [ 'beep', 'boop', 'bar' ], 'f': [ 'foo' ] } 66 ``` 67 68 An `indicator` function is provided two arguments: 69 70 - `value`: object value 71 - `key`: object index 72 73 ```javascript 74 function indicator( v, k ) { 75 console.log( '%s: %s', k, v ); 76 return v[ 0 ]; 77 } 78 79 function Foo() { 80 this.a = 'beep'; 81 this.b = 'boop'; 82 return this; 83 } 84 85 Foo.prototype = Object.create( null ); 86 Foo.prototype.c = 'foo'; 87 Foo.prototype.d = 'bar'; 88 89 var obj = new Foo(); 90 91 var out = groupIn( obj, indicator ); 92 // e.g., returns { 'b': [ 'beep', 'boop', 'bar' ], 'f': [ 'foo' ] } 93 ``` 94 95 The function accepts the following `options`: 96 97 - `returns`: specifies the output format. If the option equals `'values'`, the function outputs values. If the option equals `'keys'`, the function outputs keys. If the option equals `'*'`, the function outputs both keys and values. Default: `'values'`. 98 - `thisArg`: execution context. 99 100 By default, the function returns object values. To return object keys, set the `returns` option to `'keys'`. 101 102 ```javascript 103 function indicator( v ) { 104 return v[ 0 ]; 105 } 106 107 function Foo() { 108 this.a = 'beep'; 109 this.b = 'boop'; 110 return this; 111 } 112 113 Foo.prototype = Object.create( null ); 114 Foo.prototype.c = 'foo'; 115 Foo.prototype.d = 'bar'; 116 117 var obj = new Foo(); 118 119 var opts = { 120 'returns': 'keys' 121 }; 122 var out = groupIn( obj, opts, indicator ); 123 // e.g., returns { 'b': [ 'a', 'b', 'd' ], 'f': [ 'c' ] } 124 ``` 125 126 To return key-value pairs, set the `returns` option to `'*'`. 127 128 ```javascript 129 function indicator( v ) { 130 return v[ 0 ]; 131 } 132 133 function Foo() { 134 this.a = 'beep'; 135 this.b = 'boop'; 136 return this; 137 } 138 139 Foo.prototype = Object.create( null ); 140 Foo.prototype.c = 'foo'; 141 Foo.prototype.d = 'bar'; 142 143 var obj = new Foo(); 144 145 var opts = { 146 'returns': '*' 147 }; 148 var out = groupIn( obj, opts, indicator ); 149 // e.g., returns { 'b': [ [ 'a', 'beep' ], [ 'b', 'boop ], [ 'd', 'bar' ] ], 'f': [ [ 'c', 'foo' ] ] } 150 ``` 151 152 To set the `indicator` execution context, provide a `thisArg`. 153 154 ```javascript 155 function indicator( v ) { 156 this.count += 1; 157 return v[ 0 ]; 158 } 159 160 function Foo() { 161 this.a = 'beep'; 162 this.b = 'boop'; 163 return this; 164 } 165 166 Foo.prototype = Object.create( null ); 167 Foo.prototype.c = 'foo'; 168 Foo.prototype.d = 'bar'; 169 170 var obj = new Foo(); 171 172 var context = { 173 'count': 0 174 }; 175 var opts = { 176 'thisArg': context 177 }; 178 179 var out = groupIn( obj, opts, indicator ); 180 // e.g., returns { 'b': [ 'beep', 'boop', 'bar' ], 'f': [ 'foo' ] } 181 182 console.log( context.count ); 183 // => 4 184 ``` 185 186 </section> 187 188 <!-- /.usage --> 189 190 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 191 192 <section class="notes"> 193 194 ## Notes 195 196 - Iteration order is **not** guaranteed, as `object` key enumeration is not specified according to the [ECMAScript specification][ecma-262-for-in]. In practice, however, most engines use insertion order to sort an `object`'s keys, thus allowing for deterministic iteration. 197 198 - Because iteration order is **not** guaranteed, result order is **not** guaranteed. 199 200 - The function determines the list of own **and** inherited enumerable properties **before** invoking the provided function. Hence, any modifications made to the input `object` **after** calling this function (such as adding and removing properties) will **not** affect the list of visited properties. 201 202 - The value returned by an `indicator` function should be a value which can be serialized as an `object` key. As a counterexample, 203 204 ```javascript 205 function indicator( v ) { 206 return {}; 207 } 208 209 function Foo() { 210 this.a = 'beep'; 211 this.b = 'boop'; 212 return this; 213 } 214 215 Foo.prototype = Object.create( null ); 216 Foo.prototype.c = 'foo'; 217 Foo.prototype.d = 'bar'; 218 219 var obj = new Foo(); 220 221 var out = groupIn( obj, indicator ); 222 // e.g., returns { '[object Object]': [ 'beep', 'boop', 'foo', 'bar' ] } 223 ``` 224 225 while each group identifier is unique, all object values resolve to the same group because each group identifier serializes to the same `string`. 226 227 </section> 228 229 <!-- /.notes --> 230 231 <!-- Package usage examples. --> 232 233 <section class="examples"> 234 235 ## Examples 236 237 <!-- eslint no-undef: "error" --> 238 239 ```javascript 240 var randu = require( '@stdlib/random/base/randu' ); 241 var fromCodePoint = require( '@stdlib/string/from-code-point' ); 242 var groupIn = require( '@stdlib/utils/group-in' ); 243 244 var key; 245 var obj; 246 var out; 247 var i; 248 249 function Foo() { 250 var key; 251 var i; 252 for ( i = 0; i < 50; i++ ) { 253 key = fromCodePoint( 147+i ); 254 this[ key ] = randu(); 255 } 256 return this; 257 } 258 259 Foo.prototype = Object.create( null ); 260 for ( i = 0; i < 50; i++ ) { 261 key = fromCodePoint( 97+i ); 262 Foo.prototype[ key ] = randu(); 263 } 264 265 // Generate a random object: 266 obj = new Foo(); 267 268 // Compute the groups... 269 function indicator( v ) { 270 if ( v < 0.5 ) { 271 return 'low'; 272 } 273 return 'high'; 274 } 275 out = groupIn( obj, indicator ); 276 console.log( out ); 277 ``` 278 279 </section> 280 281 <!-- /.examples --> 282 283 <!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 284 285 <section class="references"> 286 287 </section> 288 289 <!-- /.references --> 290 291 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 292 293 <section class="links"> 294 295 [ecma-262-for-in]: http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4 296 297 </section> 298 299 <!-- /.links -->