jupyter-ijavascript-utils 1.60.1 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +40 -0
- package/Dockerfile +1 -1
- package/README.md +38 -0
- package/package.json +1 -1
- package/src/TableGenerator.js +1 -1
- package/src/aggregate.js +8 -8
- package/src/array.js +123 -117
- package/src/chain.js +14 -12
- package/src/color.js +36 -17
- package/src/date.js +29 -18
- package/src/format.js +89 -70
- package/src/group.js +2 -3
- package/src/hashMap.js +16 -16
- package/src/object.js +190 -87
package/DOCS.md
CHANGED
|
@@ -74,6 +74,8 @@ Give it a try here:
|
|
|
74
74
|
[](https://mybinder.org/v2/gh/paulroth3d/jupyter-ijavascript-utils/main?labpath=example.ipynb)
|
|
75
75
|
|
|
76
76
|
## What's New
|
|
77
|
+
* 1.62 - Update to Array.peekableIterator to include peekItr() as sugar for .peek
|
|
78
|
+
* 1.61 - Docs Updated
|
|
77
79
|
* 1.60 - Make post-processing of documents easier with {@link module:ijs.markDocumentPosition|ijs.markDocumentPosition}
|
|
78
80
|
* 1.59 -
|
|
79
81
|
* #95 - give control with page breaks. So we can render text before the page break (like for headers) - or even get the html used and render it how we want. (ex: {@link module:ijs.generatePageBreakStylesHTML|ijs.printPageBreak})
|
|
@@ -404,6 +406,44 @@ Depends on:
|
|
|
404
406
|
|
|
405
407
|
See the [How to Use]{@tutorial howToUse} section for more.
|
|
406
408
|
|
|
409
|
+
# Common Questions
|
|
410
|
+
|
|
411
|
+
## Converting Local Functions to a Local Library
|
|
412
|
+
|
|
413
|
+
Often - Jupyter is not the best place to do development, and folks would like to develop in their own favourite IDE.
|
|
414
|
+
|
|
415
|
+
You can write local modules (ex: `lib.js`) relative to your notebook, and then use `require('./lib')` to access them in your notebook. (see the section below on ESM Modules)
|
|
416
|
+
|
|
417
|
+
NOTE: re-running the require will use a `cached version` of your module, and `may not reflect changes you just made`.
|
|
418
|
+
|
|
419
|
+
(For this and other reasons, it can be helpful to have a `version` attribute to your module - to ensure the latest code is accessible)
|
|
420
|
+
|
|
421
|
+
There typically are two options:
|
|
422
|
+
|
|
423
|
+
* re-run the entire notebook
|
|
424
|
+
|
|
425
|
+
* use a "cache bypass" only for your local library. ex: [import-fresh](https://www.npmjs.com/package/import-fresh)
|
|
426
|
+
|
|
427
|
+
Using a cache bypass is fairly simple, and behaves something similar to this:
|
|
428
|
+
|
|
429
|
+
```
|
|
430
|
+
utils = reqire('jupyter-ijavascript-utils');
|
|
431
|
+
importFresh = require('import-fresh');
|
|
432
|
+
// other imports go here
|
|
433
|
+
|
|
434
|
+
//-- clear the output so it doesn't pollute with nonsense we don't care about.
|
|
435
|
+
utils.ijs.clearOutput();
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
and then load your module in a separate cell:
|
|
439
|
+
|
|
440
|
+
```
|
|
441
|
+
lib = importFresh('./lib');
|
|
442
|
+
lib.version; // 1.0.0
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
and if you change your library, you can then just run that cell again
|
|
446
|
+
|
|
407
447
|
## ESM Modules + D3
|
|
408
448
|
|
|
409
449
|
Note that we strongly recommend using this with other modules like D3 - that only support ESM modules now.
|
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -54,6 +54,8 @@ This is not intended to be the only way to accomplish many of these tasks, and a
|
|
|
54
54
|

|
|
55
55
|
|
|
56
56
|
# What's New
|
|
57
|
+
* 1.62 - Update to Array.peekableIterator to include peekItr() as sugar for .peek
|
|
58
|
+
* 1.61 - Docs Updated
|
|
57
59
|
* 1.60 - Make post-processing of documents easier with ijs.utils.markDocumentPosition
|
|
58
60
|
* 1.59 -
|
|
59
61
|
* #95 - give control with page breaks. So we can render text before the page break (like for headers) - or even get the html used and render it how we want.
|
|
@@ -132,6 +134,42 @@ found under the [docResources/notebooks](https://github.com/paulroth3d/jupyter-i
|
|
|
132
134
|
simply create a package in the folder you will run the `jupyter lab` command
|
|
133
135
|
- such as the sample one under [docResources/notebooks/package.json](https://github.com/paulroth3d/jupyter-ijavascript-utils/blob/main/docResources/notebooks/package.json))
|
|
134
136
|
|
|
137
|
+
## Converting Local Functions to a Local Library
|
|
138
|
+
|
|
139
|
+
Often - Jupyter is not the best place to do development, and folks would like to develop in their own favourite IDE.
|
|
140
|
+
|
|
141
|
+
You can write local modules (ex: `lib.js`) relative to your notebook, and then use `require('./lib')` to access them in your notebook. (see the section below on ESM Modules)
|
|
142
|
+
|
|
143
|
+
NOTE: re-running the require will use a `cached version` of your module, and `may not reflect changes you just made`.
|
|
144
|
+
|
|
145
|
+
(For this and other reasons, it can be helpful to have a `version` attribute to your module - to ensure the latest code is accessible)
|
|
146
|
+
|
|
147
|
+
There typically are two options:
|
|
148
|
+
|
|
149
|
+
* re-run the entire notebook
|
|
150
|
+
|
|
151
|
+
* use a "cache bypass" only for your local library. ex: [https://www.npmjs.com/package/import-fresh](import-fresh)
|
|
152
|
+
|
|
153
|
+
Using a cache bypass is fairly simple, and behaves somethng similar to this:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
utils = reqire('jupyter-ijavascript-utils');
|
|
157
|
+
importFresh = require('import-fresh');
|
|
158
|
+
// other imports go here
|
|
159
|
+
|
|
160
|
+
//-- clear the output so it doesn't pollute with nonsense we don't care about.
|
|
161
|
+
utils.ijs.clearOutput();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
and then load your module in a separate cell:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
lib = importFresh('./lib');
|
|
168
|
+
lib.version; // 1.0.0
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
and if you change your library, you can then just rn tat cell again
|
|
172
|
+
|
|
135
173
|
## ESM Modules + D3
|
|
136
174
|
|
|
137
175
|
Note that we strongly recommend using this with other modules like D3 - that only support ESM modules now.
|
package/package.json
CHANGED
package/src/TableGenerator.js
CHANGED
|
@@ -1751,7 +1751,7 @@ class TableGenerator {
|
|
|
1751
1751
|
const prepResults = this.prepare();
|
|
1752
1752
|
const results = {};
|
|
1753
1753
|
const createFrameList = () => new Array(prepResults.data.length).fill(undefined);
|
|
1754
|
-
prepResults.headers.forEach((header) => ObjectUtils.
|
|
1754
|
+
prepResults.headers.forEach((header) => ObjectUtils.assignIP(results, header, createFrameList()));
|
|
1755
1755
|
|
|
1756
1756
|
prepResults.data.forEach((row, rowIndex) => {
|
|
1757
1757
|
row.forEach((value, valIndex) => {
|
package/src/aggregate.js
CHANGED
|
@@ -549,7 +549,7 @@ module.exports.first = function first(collection, accessor) {
|
|
|
549
549
|
* @param {Array} collection -
|
|
550
550
|
* @returns {Number}
|
|
551
551
|
* @example
|
|
552
|
-
* utils.aggregate.
|
|
552
|
+
* utils.aggregate.length([0.87, 2.68, 5.31, 3.94, 4.13, 3.58, 3.62, 2.56]);
|
|
553
553
|
* // 8
|
|
554
554
|
*/
|
|
555
555
|
module.exports.length = function length(collection) {
|
|
@@ -684,7 +684,7 @@ module.exports.countMap = function countMap(collection, accessor, uniquifierFn)
|
|
|
684
684
|
* { station: 'A', timestamp: new Date(2022, 0, 2, 9, 30) },
|
|
685
685
|
* { station: 'B', timestamp: new Date(2022, 0, 2, 10, 0) },
|
|
686
686
|
* { station: 'A', timestamp: new Date(2022, 0, 3, 10, 0) },
|
|
687
|
-
* { station: 'B', timestamp: new Date(2022, 0, 3, 10, 0 }
|
|
687
|
+
* { station: 'B', timestamp: new Date(2022, 0, 3, 10, 0) }
|
|
688
688
|
* ]
|
|
689
689
|
* utils.aggregate.count(series, 'timestamp', (d) => d.toISOString().slice(0, 10))
|
|
690
690
|
* // { '2022-01-01': 3, '2022-01-02': 2, '2022-01-03': 2 }
|
|
@@ -744,7 +744,7 @@ module.exports.duplicates = function duplicates(collection, accessor, uniquifier
|
|
|
744
744
|
* const superSet = new Set(['a', 'b', 'c']);
|
|
745
745
|
* const data = [{ val: 'a' }, { val: 'b' }, { val: 'c' }, { val: 'd' }];
|
|
746
746
|
*
|
|
747
|
-
* aggregate.notIn(data, 'val', superSet);
|
|
747
|
+
* utils.aggregate.notIn(data, 'val', superSet);
|
|
748
748
|
* // Set('d')
|
|
749
749
|
*/
|
|
750
750
|
module.exports.notIn = function notIn(collection, accessor, targetIterator) {
|
|
@@ -768,13 +768,13 @@ module.exports.notIn = function notIn(collection, accessor, targetIterator) {
|
|
|
768
768
|
* @returns {Boolean} - whether the values in the array are truly unique
|
|
769
769
|
* @example
|
|
770
770
|
* let data = [{ val: 1 }, { val: 2 }, { val: 3 }, { val: 1 }];
|
|
771
|
-
* aggregate.isUnique(data, 'val'); // false
|
|
771
|
+
* utils.aggregate.isUnique(data, 'val'); // false
|
|
772
772
|
*
|
|
773
773
|
* let data = [{ val: 1 }, { val: 2 }, { val: 3 }];
|
|
774
|
-
* aggregate.isUnique(data, 'val'); // true
|
|
774
|
+
* utils.aggregate.isUnique(data, 'val'); // true
|
|
775
775
|
*
|
|
776
776
|
* data = ['a', 'b', 'c', 'd'];
|
|
777
|
-
* aggregate.isUnique(data); // true
|
|
777
|
+
* utils.aggregate.isUnique(data); // true
|
|
778
778
|
*/
|
|
779
779
|
module.exports.isUnique = function isUnique(collection, accessor) {
|
|
780
780
|
const cleanedFunc = ObjectUtils.evaluateFunctionOrProperty(accessor);
|
|
@@ -981,7 +981,7 @@ module.exports.percentile_99 = function percentile(collection, accessor) {
|
|
|
981
981
|
* // 0.87, 2.56, 2.68, 3.58, 3.62
|
|
982
982
|
*
|
|
983
983
|
* //-- you can also combine values to make the values clearer, by passing a function
|
|
984
|
-
* const monthPrecip =
|
|
984
|
+
* const monthPrecip = (record) => `${record.month} (${record.precip})`;
|
|
985
985
|
* utils.aggregate.topValues(collection, 3, monthPrecip, '-precip');
|
|
986
986
|
* // '2021-Oct (5.31)', '2021-Dec (4.13)', '2022-Mar (3.98)'
|
|
987
987
|
* ```
|
|
@@ -998,7 +998,7 @@ module.exports.percentile_99 = function percentile(collection, accessor) {
|
|
|
998
998
|
*
|
|
999
999
|
* //-- bottom 5 values
|
|
1000
1000
|
* utils.aggregate.topValues(collection, 5, null, '');
|
|
1001
|
-
* //
|
|
1001
|
+
* // [0.87, 2.56, 2.68, 3.58, 3.62]
|
|
1002
1002
|
* ```
|
|
1003
1003
|
*
|
|
1004
1004
|
* @param {Array} collection - Collection of values we want to get the top values from
|
package/src/array.js
CHANGED
|
@@ -63,18 +63,16 @@ const ArrayUtils = module.exports;
|
|
|
63
63
|
* @type {Function}
|
|
64
64
|
* @example
|
|
65
65
|
*
|
|
66
|
-
* [3,5,1,2,4].sort(utils.
|
|
67
|
-
* //
|
|
68
|
-
* [1,2,3,4,5]
|
|
66
|
+
* [3,5,1,2,4].sort(utils.array.SIMPLE_ASCENDING)
|
|
67
|
+
* // [1,2,3,4,5]
|
|
69
68
|
*/
|
|
70
69
|
module.exports.SORT_ASCENDING = (a, b) => a === b ? 0 : a > b ? 1 : -1;
|
|
71
70
|
|
|
72
71
|
/**
|
|
73
72
|
* Simple descending sort function
|
|
74
73
|
* @example
|
|
75
|
-
* [3,5,1,2,4].sort(utils.
|
|
76
|
-
* //
|
|
77
|
-
* [5,4,3,2,1]
|
|
74
|
+
* [3,5,1,2,4].sort(utils.array.SORT_DESCENDING)
|
|
75
|
+
* // [5,4,3,2,1]
|
|
78
76
|
* @type {Function}
|
|
79
77
|
*/
|
|
80
78
|
module.exports.SORT_DESCENDING = (a, b) => a === b ? 0 : a > b ? -1 : 1;
|
|
@@ -83,16 +81,17 @@ module.exports.SORT_DESCENDING = (a, b) => a === b ? 0 : a > b ? -1 : 1;
|
|
|
83
81
|
* Creates a sort function based on fields of an object.
|
|
84
82
|
*
|
|
85
83
|
* ```
|
|
86
|
-
*
|
|
84
|
+
* [{score: 200, name: 'jane'}, {score: 300, name: 'john'}, {score: 300, name: 'jonny'}];
|
|
87
85
|
* // sort by score descending, and then by name ascending
|
|
88
|
-
* sampleData.sort(utils.array.createSort('-score','name'))
|
|
86
|
+
* sampleData.sort(utils.array.createSort('-score','name'));
|
|
87
|
+
* // [{ score: 300, name: 'john' }, { score: 300, name: 'jonny' },{ score: 200, name: 'jane' }]
|
|
89
88
|
* ```
|
|
90
89
|
*
|
|
91
90
|
* @example
|
|
92
91
|
*
|
|
93
92
|
* sampleData = [{i:4}, {v:2}, {v:1}, {v:3}];
|
|
94
93
|
* sortedData = sampleData.sort(
|
|
95
|
-
* utils.createSort('-v')
|
|
94
|
+
* utils.array.createSort('-v')
|
|
96
95
|
* );
|
|
97
96
|
* // [{v:4}, {v:3}, {v:2}, {v:1}]
|
|
98
97
|
*
|
|
@@ -427,16 +426,16 @@ module.exports.applyArrayValue = function applyArrayValue(collection, path, valu
|
|
|
427
426
|
* cities = utils.object.extractObjectProperty('city');
|
|
428
427
|
* // ['Seattle', 'New York', 'Chicago'];
|
|
429
428
|
*
|
|
430
|
-
* //--
|
|
431
|
-
* geocodedCities =
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
* // { city: 'Chicago', state: 'IL', country: 'USA' }]
|
|
429
|
+
* //-- get a separate dataset that needs to be joined, like geocodeCity(cities);
|
|
430
|
+
* geocodedCities = [{ city: 'Seattle', state: 'WA', country: 'USA' },
|
|
431
|
+
* { city: 'New York', state: 'NY', country: 'USA' },
|
|
432
|
+
* { city: 'Chicago', state: 'IL', country: 'USA' }];
|
|
435
433
|
*
|
|
436
|
-
* utils.applyArrayValues(weather, 'geo', geocodedCities);
|
|
434
|
+
* utils.array.applyArrayValues(weather, 'geo', geocodedCities);
|
|
437
435
|
* // [{ id: 1, city: 'Seattle', month: 'Aug', precip: 0.87, geo: { city: 'Seattle', state: 'WA', country: 'USA' } },
|
|
438
436
|
* // { id: 3, city: 'New York', month: 'Apr', precip: 3.94, geo: { city: 'New York', state: 'NY', country: 'USA' } },
|
|
439
437
|
* // { id: 6, city: 'Chicago', month: 'Apr', precip: 3.62, geo: { city: 'Chicago', state: 'IL', country: 'USA' } }];
|
|
438
|
+
* ```
|
|
440
439
|
*
|
|
441
440
|
* Note that traditional [Array.map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
|
|
442
441
|
* works best for if you are working with objects completely in memory.
|
|
@@ -505,14 +504,14 @@ module.exports.size = function size(length, defaultValue) {
|
|
|
505
504
|
*
|
|
506
505
|
* utils.array.arange(10, 1)
|
|
507
506
|
* .map((val) => `item ${val}`);
|
|
508
|
-
*
|
|
509
|
-
* [
|
|
510
|
-
* 'item 1', 'item 2',
|
|
511
|
-
* 'item 3', 'item 4',
|
|
512
|
-
* 'item 5', 'item 6',
|
|
513
|
-
* 'item 7', 'item 8',
|
|
514
|
-
* 'item 9', 'item 10'
|
|
515
|
-
* ]
|
|
507
|
+
*
|
|
508
|
+
* // [
|
|
509
|
+
* // 'item 1', 'item 2',
|
|
510
|
+
* // 'item 3', 'item 4',
|
|
511
|
+
* // 'item 5', 'item 6',
|
|
512
|
+
* // 'item 7', 'item 8',
|
|
513
|
+
* // 'item 9', 'item 10'
|
|
514
|
+
* // ]
|
|
516
515
|
* @param {Number} length - the number of items toreturn
|
|
517
516
|
* @param {Number} [start=0] - the starting number
|
|
518
517
|
* @param {Number} [step=1] - the number to increment for each step
|
|
@@ -573,13 +572,13 @@ module.exports.arrayLength2d = function arrayLength2d(targetArray) {
|
|
|
573
572
|
* @example
|
|
574
573
|
*
|
|
575
574
|
* baseArray = [ 0, 1, 2, 3, 4 ];
|
|
576
|
-
* utils.array.transpose(utils.array.arrange(5))
|
|
577
|
-
*
|
|
578
|
-
* [ [ 0 ],
|
|
579
|
-
* [ 1 ],
|
|
580
|
-
* [ 2 ],
|
|
581
|
-
* [ 3 ],
|
|
582
|
-
* [ 4 ] ]
|
|
575
|
+
* utils.array.transpose(utils.array.arrange(5));
|
|
576
|
+
*
|
|
577
|
+
* // [ [ 0 ],
|
|
578
|
+
* // [ 1 ],
|
|
579
|
+
* // [ 2 ],
|
|
580
|
+
* // [ 3 ],
|
|
581
|
+
* // [ 4 ] ]
|
|
583
582
|
*/
|
|
584
583
|
module.exports.transpose = function transpose(matrix) {
|
|
585
584
|
//-- fast fail
|
|
@@ -618,22 +617,22 @@ module.exports.transpose = function transpose(matrix) {
|
|
|
618
617
|
* @example
|
|
619
618
|
*
|
|
620
619
|
* baseArray = utils.array.arrange(12);
|
|
621
|
-
* [
|
|
622
|
-
* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
|
623
|
-
* ]
|
|
620
|
+
* // [
|
|
621
|
+
* // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
|
|
622
|
+
* // ]
|
|
624
623
|
*
|
|
625
624
|
* //-- reshape the 1d array based on 3 columns
|
|
626
625
|
* newArray = utils.array.reshape(baseArray, 3)
|
|
627
|
-
* [ [ 0, 1, 2 ],
|
|
628
|
-
* [ 3, 4, 5 ],
|
|
629
|
-
* [ 6, 7, 8 ],
|
|
630
|
-
* [ 9, 10, 11 ] ];
|
|
626
|
+
* // [ [ 0, 1, 2 ],
|
|
627
|
+
* // [ 3, 4, 5 ],
|
|
628
|
+
* // [ 6, 7, 8 ],
|
|
629
|
+
* // [ 9, 10, 11 ] ];
|
|
631
630
|
*
|
|
632
631
|
* //-- now reshape the 4x3 array to 3x4
|
|
633
632
|
* utils.array.reshape(newArray, 4);
|
|
634
|
-
* [ [ 0, 1, 2, 3 ],
|
|
635
|
-
* [ 4, 5, 6, 7 ],
|
|
636
|
-
* [ 8, 9, 10, 11 ] ]
|
|
633
|
+
* // [ [ 0, 1, 2, 3 ],
|
|
634
|
+
* // [ 4, 5, 6, 7 ],
|
|
635
|
+
* // [ 8, 9, 10, 11 ] ]
|
|
637
636
|
*/
|
|
638
637
|
module.exports.reshape = function reshape(sourceArray, numColumns) {
|
|
639
638
|
const results = [];
|
|
@@ -710,7 +709,7 @@ module.exports.clone = function clone(target) {
|
|
|
710
709
|
* // [ 3, 0 ], [ 3, 1 ], [ 3, 2 ], [ 3, 3 ]
|
|
711
710
|
* // ]
|
|
712
711
|
*
|
|
713
|
-
*
|
|
712
|
+
* gridPositions.forEach((value, index) => {
|
|
714
713
|
* const [x, y] = gridPositions[index];
|
|
715
714
|
* console.log(`placing ${value} in row:${x}, column:${y}`);
|
|
716
715
|
* });
|
|
@@ -779,41 +778,41 @@ module.exports.arangeMulti = module.exports.arrangeMulti;
|
|
|
779
778
|
* isHeader1('This describes section A'); // false
|
|
780
779
|
*
|
|
781
780
|
* indexedData = utils.array.indexify(data, isHeader1);
|
|
782
|
-
* [
|
|
783
|
-
* { entry: 'Heading', section: [ 0 ], subIndex: 1 },
|
|
784
|
-
* { entry: '# Overview', section: [ 1 ], subIndex: 0 },
|
|
785
|
-
* {
|
|
786
|
-
* entry: 'This entire list is a hierarchy of data.',
|
|
787
|
-
* section: [ 1 ],
|
|
788
|
-
* subIndex: 1
|
|
789
|
-
* },
|
|
790
|
-
* { entry: '# Section A', section: [ 2 ], subIndex: 0 },
|
|
791
|
-
* { entry: 'This describes section A', section: [ 2 ], subIndex: 1 },
|
|
792
|
-
* { entry: '## SubSection 1', section: [ 2 ], subIndex: 2 },
|
|
793
|
-
* {
|
|
794
|
-
* entry: 'With a subsection belonging to Section A',
|
|
795
|
-
* section: [ 2 ],
|
|
796
|
-
* subIndex: 3
|
|
797
|
-
* },
|
|
798
|
-
* { entry: '## SubSection 2', section: [ 2 ], subIndex: 4 },
|
|
799
|
-
* {
|
|
800
|
-
* entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
|
|
801
|
-
* section: [ 2 ],
|
|
802
|
-
* subIndex: 5
|
|
803
|
-
* },
|
|
804
|
-
* { entry: '# Section B', section: [ 3 ], subIndex: 0 },
|
|
805
|
-
* {
|
|
806
|
-
* entry: 'With an entirely unrelated section B, that is sibling to Section A',
|
|
807
|
-
* section: [ 3 ],
|
|
808
|
-
* subIndex: 1
|
|
809
|
-
* },
|
|
810
|
-
* { entry: '## SubSection 1', section: [ 3 ], subIndex: 2 },
|
|
811
|
-
* {
|
|
812
|
-
* entry: 'And another subsection 1, but this time related to Section B.',
|
|
813
|
-
* section: [ 3 ],
|
|
814
|
-
* subIndex: 3
|
|
815
|
-
* }
|
|
816
|
-
* ];
|
|
781
|
+
* // [
|
|
782
|
+
* // { entry: 'Heading', section: [ 0 ], subIndex: 1 },
|
|
783
|
+
* // { entry: '# Overview', section: [ 1 ], subIndex: 0 },
|
|
784
|
+
* // {
|
|
785
|
+
* // entry: 'This entire list is a hierarchy of data.',
|
|
786
|
+
* // section: [ 1 ],
|
|
787
|
+
* // subIndex: 1
|
|
788
|
+
* // },
|
|
789
|
+
* // { entry: '# Section A', section: [ 2 ], subIndex: 0 },
|
|
790
|
+
* // { entry: 'This describes section A', section: [ 2 ], subIndex: 1 },
|
|
791
|
+
* // { entry: '## SubSection 1', section: [ 2 ], subIndex: 2 },
|
|
792
|
+
* // {
|
|
793
|
+
* // entry: 'With a subsection belonging to Section A',
|
|
794
|
+
* // section: [ 2 ],
|
|
795
|
+
* // subIndex: 3
|
|
796
|
+
* // },
|
|
797
|
+
* // { entry: '## SubSection 2', section: [ 2 ], subIndex: 4 },
|
|
798
|
+
* // {
|
|
799
|
+
* // entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
|
|
800
|
+
* // section: [ 2 ],
|
|
801
|
+
* // subIndex: 5
|
|
802
|
+
* // },
|
|
803
|
+
* // { entry: '# Section B', section: [ 3 ], subIndex: 0 },
|
|
804
|
+
* // {
|
|
805
|
+
* // entry: 'With an entirely unrelated section B, that is sibling to Section A',
|
|
806
|
+
* // section: [ 3 ],
|
|
807
|
+
* // subIndex: 1
|
|
808
|
+
* // },
|
|
809
|
+
* // { entry: '## SubSection 1', section: [ 3 ], subIndex: 2 },
|
|
810
|
+
* // {
|
|
811
|
+
* // entry: 'And another subsection 1, but this time related to Section B.',
|
|
812
|
+
* // section: [ 3 ],
|
|
813
|
+
* // subIndex: 3
|
|
814
|
+
* // }
|
|
815
|
+
* // ];
|
|
817
816
|
* ```
|
|
818
817
|
*
|
|
819
818
|
* Note that this only indexes elements by the first header.
|
|
@@ -924,8 +923,8 @@ module.exports.indexify = function indexify(source, ...sectionIndicatorFunctions
|
|
|
924
923
|
* For example, say you got a string formatted like this:
|
|
925
924
|
*
|
|
926
925
|
* ```
|
|
927
|
-
* hardSpacedString =
|
|
928
|
-
* id first_name last_name city email gender ip_address airport_code car_model_year
|
|
926
|
+
* hardSpacedString = '' +
|
|
927
|
+
* `id first_name last_name city email gender ip_address airport_code car_model_year
|
|
929
928
|
* -- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
|
|
930
929
|
* 1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
|
|
931
930
|
* 2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
|
|
@@ -976,8 +975,8 @@ module.exports.multiLineSubstr = function multiLineSubstr(target, start, length)
|
|
|
976
975
|
* For example, say you got a string formatted like this:
|
|
977
976
|
*
|
|
978
977
|
* ```
|
|
979
|
-
* hardSpacedString =
|
|
980
|
-
* id first_name last_name city email gender ip_address airport_code car_model_year
|
|
978
|
+
* hardSpacedString = '' +
|
|
979
|
+
* `id first_name last_name city email gender ip_address airport_code car_model_year
|
|
981
980
|
* -- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
|
|
982
981
|
* 1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
|
|
983
982
|
* 2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
|
|
@@ -1029,8 +1028,8 @@ module.exports.multiLineSubstring = function multiLineSubstring(target, startPos
|
|
|
1029
1028
|
* For example:
|
|
1030
1029
|
*
|
|
1031
1030
|
* ```
|
|
1032
|
-
* hardSpacedString =
|
|
1033
|
-
* id first_name last_name city email gender ip_address airport_code car_model_year
|
|
1031
|
+
* hardSpacedString = '' +
|
|
1032
|
+
* `id first_name last_name city email gender ip_address airport_code car_model_year
|
|
1034
1033
|
* -- ---------- ---------- ----------- ---------------------------- ------ --------------- ------------ --------------
|
|
1035
1034
|
* 1 Thekla Brokenshaw Chicago tbrokenshaw0@kickstarter.com Female 81.118.170.238 CXI 2003
|
|
1036
1035
|
* 2 Lexi Dugall New York ldugall1@fc2.com Female 255.140.25.31 LBH 2005
|
|
@@ -1072,7 +1071,7 @@ module.exports.multiLineSubstring = function multiLineSubstring(target, startPos
|
|
|
1072
1071
|
* cityStartingCharacter = substrPairs[3][0]; // 25
|
|
1073
1072
|
* cityColumnLength = substrPairs[3][1]; // 12
|
|
1074
1073
|
*
|
|
1075
|
-
* cityData =
|
|
1074
|
+
* cityData = utils.array.multiLineSubstr(hardSpacedString, cityStartingCharacter, cityColumnLength);
|
|
1076
1075
|
* // ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', 'Lainqu ', 'Los Angeles ']
|
|
1077
1076
|
* ```
|
|
1078
1077
|
*
|
|
@@ -1080,18 +1079,18 @@ module.exports.multiLineSubstring = function multiLineSubstring(target, startPos
|
|
|
1080
1079
|
*
|
|
1081
1080
|
* ```
|
|
1082
1081
|
* results = substrPairs.map(
|
|
1083
|
-
* ([startingPos, length]) =>
|
|
1082
|
+
* ([startingPos, length]) => utils.array.multiLineSubstr(hardSpacedString, startingPos, length)
|
|
1084
1083
|
* );
|
|
1085
1084
|
*
|
|
1086
|
-
* [['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
|
|
1087
|
-
* ['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
|
|
1088
|
-
* ['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
|
|
1089
|
-
* ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
|
|
1090
|
-
* ['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
|
|
1091
|
-
* ['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
|
|
1092
|
-
* ['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
|
|
1093
|
-
* ['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
|
|
1094
|
-
* ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
|
|
1085
|
+
* // [['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
|
|
1086
|
+
* // ['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
|
|
1087
|
+
* // ['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
|
|
1088
|
+
* // ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
|
|
1089
|
+
* // ['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
|
|
1090
|
+
* // ['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
|
|
1091
|
+
* // ['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
|
|
1092
|
+
* // ['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
|
|
1093
|
+
* // ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
|
|
1095
1094
|
* ```
|
|
1096
1095
|
*
|
|
1097
1096
|
* We can then transpose the array to give us the format we might expect (non DataFrame centric)
|
|
@@ -1154,17 +1153,17 @@ module.exports.multiStepReduce = function multiStepReduce(list, fn, initialValue
|
|
|
1154
1153
|
* // [ 3, 11, 11, 12, 29, 7, 16, 13, 15 ];
|
|
1155
1154
|
*
|
|
1156
1155
|
*
|
|
1157
|
-
* results = utils.array.extractFromHardSpacedTable(
|
|
1156
|
+
* results = utils.array.extractFromHardSpacedTable(hardSpacedString, columnWidths);
|
|
1158
1157
|
*
|
|
1159
|
-
* [['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
|
|
1160
|
-
* ['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
|
|
1161
|
-
* ['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
|
|
1162
|
-
* ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
|
|
1163
|
-
* ['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
|
|
1164
|
-
* ['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
|
|
1165
|
-
* ['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
|
|
1166
|
-
* ['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
|
|
1167
|
-
* ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
|
|
1158
|
+
* // [['id ', '-- ', '1 ', '2 ', '3 ', '4 ', '5 '],
|
|
1159
|
+
* // ['first_name ', '---------- ', 'Thekla ', 'Lexi ', 'Shawna ', 'Gin...', ...],
|
|
1160
|
+
* // ['last_name ', '---------- ', 'Brokenshaw ', 'Dugall ', 'Burghill ', 'Twe...', ...],
|
|
1161
|
+
* // ['city ', '----------- ', 'Chicago ', 'New York ', 'London ', ...],
|
|
1162
|
+
* // ['email ', '---------------------------- ', 'tbrokenshaw0...', ...],
|
|
1163
|
+
* // ['gender ', '------ ', 'Female ', 'Female ', 'Female ', 'Female ', 'Female '],
|
|
1164
|
+
* // ['ip_address ', '--------------- ', '81.118.170.238 ', '255.140.25.31 ', ...],
|
|
1165
|
+
* // ['airport_code ', '------------ ', 'CXI ', 'LBH ', 'GBA ...', ...],
|
|
1166
|
+
* // ['car_model_year', '--------------', '2003 ', '2005 ', '2004 ...', ...]]
|
|
1168
1167
|
* ```
|
|
1169
1168
|
*
|
|
1170
1169
|
* We can then transpose the array to give us the format we might expect (non DataFrame centric)
|
|
@@ -1211,9 +1210,7 @@ module.exports.extractFromHardSpacedTable = function extractFromHardSpacedTable(
|
|
|
1211
1210
|
/**
|
|
1212
1211
|
* Create an iterator for an array that allows for peeking next values.
|
|
1213
1212
|
*
|
|
1214
|
-
*
|
|
1215
|
-
* @example
|
|
1216
|
-
*
|
|
1213
|
+
* ```
|
|
1217
1214
|
* source = [0, 1, 2, 3, 4, 5];
|
|
1218
1215
|
*
|
|
1219
1216
|
* // also quite helpful for document.querySelector(...)
|
|
@@ -1222,22 +1219,26 @@ module.exports.extractFromHardSpacedTable = function extractFromHardSpacedTable(
|
|
|
1222
1219
|
* console.log(itr.next()); // { done: false, value: 0 }
|
|
1223
1220
|
*
|
|
1224
1221
|
* //-- peek without moving the iterator
|
|
1225
|
-
*
|
|
1226
|
-
* console.log(
|
|
1227
|
-
* console.log(
|
|
1228
|
-
* console.log(
|
|
1229
|
-
* console.log(
|
|
1230
|
-
* console.log(peekItr.next()); // { done: true, value: 5 }
|
|
1222
|
+
* console.log(itr.peek.next()); // { done: false, value: 1 }
|
|
1223
|
+
* console.log(itr.peek.next()); // { done: false, value: 2 }
|
|
1224
|
+
* console.log(itr.peek.next()); // { done: false, value: 3 }
|
|
1225
|
+
* console.log(itr.peek.next()); // { done: false, value: 4 }
|
|
1226
|
+
* console.log(itr.peek.next()); // { done: true, value: 5 }
|
|
1231
1227
|
*
|
|
1232
1228
|
* //-- move the main iterator
|
|
1233
1229
|
* console.log(itr.next()); // { done: false, value: 1 }
|
|
1230
|
+
* ```
|
|
1234
1231
|
*
|
|
1235
1232
|
* Of course, for each will always work
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1233
|
+
*
|
|
1234
|
+
* ```
|
|
1235
|
+
* for (let i of new utils.array.PeekableArrayIterator(source)) {
|
|
1238
1236
|
* console.log(i);
|
|
1239
1237
|
* }
|
|
1240
1238
|
* // 1\n2\n3\n4\n5
|
|
1239
|
+
* ```
|
|
1240
|
+
*
|
|
1241
|
+
* @see https://www.npmjs.com/package/peekable-array-iterator
|
|
1241
1242
|
*/
|
|
1242
1243
|
class PeekableArrayIterator {
|
|
1243
1244
|
/**
|
|
@@ -1262,9 +1263,12 @@ class PeekableArrayIterator {
|
|
|
1262
1263
|
}
|
|
1263
1264
|
return undefined;
|
|
1264
1265
|
})();
|
|
1266
|
+
this.peekItr = function peekItr() {
|
|
1267
|
+
return this.peek;
|
|
1268
|
+
};
|
|
1265
1269
|
|
|
1266
1270
|
this.i += 1;
|
|
1267
|
-
return { done: this.i >= this.array.length
|
|
1271
|
+
return { done: this.i >= this.array.length, value: this.array[this.i] };
|
|
1268
1272
|
}
|
|
1269
1273
|
/* eslint-enable wrap-iife */
|
|
1270
1274
|
}
|
|
@@ -1458,9 +1462,11 @@ module.exports.asyncWaitAndChain = (seconds, fn, rows) => {
|
|
|
1458
1462
|
* ```
|
|
1459
1463
|
* categoryValues = ['rock', 'paper', 'scissors'];
|
|
1460
1464
|
*
|
|
1465
|
+
* //-- resizes an array to be shorter - truncating
|
|
1461
1466
|
* utils.array.resize(categoryValues, 2); // ['rock', 'paper']
|
|
1462
|
-
*
|
|
1463
|
-
*
|
|
1467
|
+
*
|
|
1468
|
+
* //-- resizes an array to be longer - filling with undefined
|
|
1469
|
+
* utils.array.resize(categoryValues, 7); // ['rock', 'paper', 'scissors', undefined, undefined, undefined, undefined];
|
|
1464
1470
|
* ```
|
|
1465
1471
|
*
|
|
1466
1472
|
* @param {Array} sourceList - array of values
|