jupyter-ijavascript-utils 1.31.0 → 1.32.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 +1 -0
- package/Dockerfile +1 -1
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/array.js +179 -0
package/DOCS.md
CHANGED
|
@@ -75,6 +75,7 @@ Give it a try here:
|
|
|
75
75
|
|
|
76
76
|
## What's New
|
|
77
77
|
|
|
78
|
+
* 1.32 - Array.indexify to identify sections within a 1d array into a hierarchy.
|
|
78
79
|
* 1.31 - harden Array.transpose for arrays with nulls, and Table.generateTSV
|
|
79
80
|
* 1.30 - add Format.wordWrap and Format.lineCount
|
|
80
81
|
* 1.29 - Updated TableGenerator.format method
|
package/Dockerfile
CHANGED
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ This is not intended to be the only way to accomplish many of these tasks, and a
|
|
|
55
55
|
|
|
56
56
|
# What's New
|
|
57
57
|
|
|
58
|
+
* 1.32 - Array.indexify to identify sections within a 1d array into a hierarchy.
|
|
58
59
|
* 1.31 - harden Array.transpose for arrays with nulls, and Table.generateTSV
|
|
59
60
|
* 1.30 - add Format.wordWrap and Format.lineCount
|
|
60
61
|
* 1.29 - Updated TableGenerator.format method
|
package/package.json
CHANGED
package/src/array.js
CHANGED
|
@@ -17,6 +17,7 @@ require('./_types/global');
|
|
|
17
17
|
* * {@link module:array.createSort|array.createSort(sortIndex, sortIndex, ...)} - generates a sorting function
|
|
18
18
|
* * {@link module:array.SORT_ASCENDING|array.SORT_ASCENDING} - common ascending sorting function for array.sort()
|
|
19
19
|
* * {@link module:array.SORT_DESCENDING|array.SORT_DESCENDING} - common descending sorting function for array.sort()
|
|
20
|
+
* * {@link module:array.indexify|array.indexify} - identify sections within a 1d array to create a hierarchy.
|
|
20
21
|
* * Rearrange Array
|
|
21
22
|
* * {@link module:array.reshape|array.reshape} - reshapes an array to a size of rows and columns
|
|
22
23
|
* * {@link module:array.transpose|array.transpose} - transposes (flips - the array along the diagonal)
|
|
@@ -504,3 +505,181 @@ module.exports.arrangeMulti = function arangeMulti(...dimensions) {
|
|
|
504
505
|
return ArrayUtils.size(currentDimension, () => ArrayUtils.clone(childDimensionalValue));
|
|
505
506
|
};
|
|
506
507
|
module.exports.arangeMulti = module.exports.arrangeMulti;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Create a unique number index for each element in an array,
|
|
511
|
+
* alternatively using additional functions to indicate hierarchies of data.
|
|
512
|
+
*
|
|
513
|
+
* For example, markdown can be considered a hierarchy of data:
|
|
514
|
+
*
|
|
515
|
+
* ```
|
|
516
|
+
* markdownList = `# Overview
|
|
517
|
+
* This entire list is a hierarchy of data.
|
|
518
|
+
*
|
|
519
|
+
* # Section A
|
|
520
|
+
* This describes section A
|
|
521
|
+
*
|
|
522
|
+
* ## SubSection 1
|
|
523
|
+
* With a subsection belonging to Section A
|
|
524
|
+
*
|
|
525
|
+
* ## SubSection 2
|
|
526
|
+
* And another subsection sibling to SubSection 1, but also under Section A.
|
|
527
|
+
*
|
|
528
|
+
* # Section B
|
|
529
|
+
* With an entirely unrelated section B, that is sibling to Section A
|
|
530
|
+
*
|
|
531
|
+
* ## SubSection 1
|
|
532
|
+
* And another subsection 1, but this time related to Section B.`;
|
|
533
|
+
* ```
|
|
534
|
+
*
|
|
535
|
+
* And we want to convert this 1d array into a hierarchy.
|
|
536
|
+
*
|
|
537
|
+
* ```
|
|
538
|
+
* data = markdownList.split('\n')
|
|
539
|
+
* .filter(line => line ? true : false); // check for empty lines
|
|
540
|
+
*
|
|
541
|
+
* utils.format.consoleLines( data, 4);
|
|
542
|
+
* // ['# Overview',
|
|
543
|
+
* // 'This entire list is a hierarchy of data.',
|
|
544
|
+
* // '# Section A',
|
|
545
|
+
* // 'This describes section A',;
|
|
546
|
+
*
|
|
547
|
+
* //-- functions that return True if we are in a new "group"
|
|
548
|
+
* isHeader1 = (str) => str.startsWith('# ');
|
|
549
|
+
*
|
|
550
|
+
* isHeader1('# Overview'); // true
|
|
551
|
+
* isHeader1('This entire list is a hierarchy of data'); // false
|
|
552
|
+
* isHeader1('# Section A'); // true
|
|
553
|
+
* isHeader1('This describes section A'); // false
|
|
554
|
+
*
|
|
555
|
+
* indexedData = utils.array.indexify(data, isHeader1);
|
|
556
|
+
* [
|
|
557
|
+
* { entry: 'Heading', section: [ 0 ], subIndex: 1 },
|
|
558
|
+
* { entry: '# Overview', section: [ 1 ], subIndex: 0 },
|
|
559
|
+
* {
|
|
560
|
+
* entry: 'This entire list is a hierarchy of data.',
|
|
561
|
+
* section: [ 1 ],
|
|
562
|
+
* subIndex: 1
|
|
563
|
+
* },
|
|
564
|
+
* { entry: '# Section A', section: [ 2 ], subIndex: 0 },
|
|
565
|
+
* { entry: 'This describes section A', section: [ 2 ], subIndex: 1 },
|
|
566
|
+
* { entry: '## SubSection 1', section: [ 2 ], subIndex: 2 },
|
|
567
|
+
* {
|
|
568
|
+
* entry: 'With a subsection belonging to Section A',
|
|
569
|
+
* section: [ 2 ],
|
|
570
|
+
* subIndex: 3
|
|
571
|
+
* },
|
|
572
|
+
* { entry: '## SubSection 2', section: [ 2 ], subIndex: 4 },
|
|
573
|
+
* {
|
|
574
|
+
* entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
|
|
575
|
+
* section: [ 2 ],
|
|
576
|
+
* subIndex: 5
|
|
577
|
+
* },
|
|
578
|
+
* { entry: '# Section B', section: [ 3 ], subIndex: 0 },
|
|
579
|
+
* {
|
|
580
|
+
* entry: 'With an entirely unrelated section B, that is sibling to Section A',
|
|
581
|
+
* section: [ 3 ],
|
|
582
|
+
* subIndex: 1
|
|
583
|
+
* },
|
|
584
|
+
* { entry: '## SubSection 1', section: [ 3 ], subIndex: 2 },
|
|
585
|
+
* {
|
|
586
|
+
* entry: 'And another subsection 1, but this time related to Section B.',
|
|
587
|
+
* section: [ 3 ],
|
|
588
|
+
* subIndex: 3
|
|
589
|
+
* }
|
|
590
|
+
* ];
|
|
591
|
+
* ```
|
|
592
|
+
*
|
|
593
|
+
* Note that this only indexes elements by the first header.
|
|
594
|
+
*
|
|
595
|
+
* To index this with two levels of hierarchy, we can pass another function.
|
|
596
|
+
*
|
|
597
|
+
* ```
|
|
598
|
+
* isHeader2 = (str) => str.startsWith('## ');
|
|
599
|
+
*
|
|
600
|
+
* isHeader2('# Overview'); // false
|
|
601
|
+
* isHeader2('This entire list is a hierarchy of data'); // false
|
|
602
|
+
* isHeader2('# Section A'); // true
|
|
603
|
+
* isHeader2('This describes section A'); // false
|
|
604
|
+
*
|
|
605
|
+
* indexedData = utils.array.indexify(data, isHeader1, isHeader2);
|
|
606
|
+
* // [
|
|
607
|
+
* // { entry: 'Heading', section: [ 0, 0 ], subIndex: 1 },
|
|
608
|
+
* // { entry: '# Overview', section: [ 1, 0 ], subIndex: 0 },
|
|
609
|
+
* // {
|
|
610
|
+
* // entry: 'This entire list is a hierarchy of data.',
|
|
611
|
+
* // section: [ 1, 0 ],
|
|
612
|
+
* // subIndex: 1
|
|
613
|
+
* // },
|
|
614
|
+
* // { entry: '# Section A', section: [ 2, 0 ], subIndex: 0 },
|
|
615
|
+
* // { entry: 'This describes section A', section: [ 2, 0 ], subIndex: 1 },
|
|
616
|
+
* // { entry: '## SubSection 1', section: [ 2, 1 ], subIndex: 0 },
|
|
617
|
+
* // {
|
|
618
|
+
* // entry: 'With a subsection belonging to Section A',
|
|
619
|
+
* // section: [ 2, 1 ],
|
|
620
|
+
* // subIndex: 1
|
|
621
|
+
* // },
|
|
622
|
+
* // { entry: '## SubSection 2', section: [ 2, 2 ], subIndex: 0 },
|
|
623
|
+
* // {
|
|
624
|
+
* // entry: 'And another subsection sibling to SubSection 1, but also under Section A.',
|
|
625
|
+
* // section: [ 2, 2 ],
|
|
626
|
+
* // subIndex: 1
|
|
627
|
+
* // },
|
|
628
|
+
* // { entry: '# Section B', section: [ 3, 0 ], subIndex: 0 },
|
|
629
|
+
* // {
|
|
630
|
+
* // entry: 'With an entirely unrelated section B, that is sibling to Section A',
|
|
631
|
+
* // section: [ 3, 0 ],
|
|
632
|
+
* // subIndex: 1
|
|
633
|
+
* // },
|
|
634
|
+
* // { entry: '## SubSection 1', section: [ 3, 1 ], subIndex: 0 },
|
|
635
|
+
* // {
|
|
636
|
+
* // entry: 'And another subsection 1, but this time related to Section B.',
|
|
637
|
+
* // section: [ 3, 1 ],
|
|
638
|
+
* // subIndex: 1
|
|
639
|
+
* // }
|
|
640
|
+
* // ];
|
|
641
|
+
* ```
|
|
642
|
+
*/
|
|
643
|
+
module.exports.indexify = function indexify(source, ...sectionIndicatorFunctions) {
|
|
644
|
+
const functionSignature = 'indexify(source, ...sectionIndicatorFunctions)';
|
|
645
|
+
|
|
646
|
+
const counters = new Array(sectionIndicatorFunctions.length).fill(0);
|
|
647
|
+
let subIndex = 0;
|
|
648
|
+
// counters[counters.length - 1] = -1;
|
|
649
|
+
|
|
650
|
+
//-- validate inputs
|
|
651
|
+
if (!Array.isArray(source)) {
|
|
652
|
+
throw new Error(`${functionSignature}: source must be an array`);
|
|
653
|
+
}
|
|
654
|
+
sectionIndicatorFunctions.forEach((fn) => {
|
|
655
|
+
if (typeof fn !== 'function') {
|
|
656
|
+
throw new Error(`${functionSignature}: all section indicators passed must be functions`);
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
const results = source.map((entry) => {
|
|
661
|
+
let isNewSectionTripped = false;
|
|
662
|
+
|
|
663
|
+
sectionIndicatorFunctions.forEach((fn, index) => {
|
|
664
|
+
if (isNewSectionTripped) {
|
|
665
|
+
counters[index] = 0;
|
|
666
|
+
} else {
|
|
667
|
+
isNewSectionTripped = fn(entry) ? true : false;
|
|
668
|
+
|
|
669
|
+
if (isNewSectionTripped) {
|
|
670
|
+
counters[index] += 1;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
if (isNewSectionTripped) {
|
|
676
|
+
subIndex = 0;
|
|
677
|
+
} else {
|
|
678
|
+
subIndex += 1;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
return ({ entry, section: [...counters], subIndex });
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
return results;
|
|
685
|
+
};
|