1+ /**
2+ * Counts items in a string, an array, or an iterable in a similar way as in Python.
3+ *
4+ * @class
5+ */
6+ class CollectionCounter extends Map {
7+ /**
8+ * Create a counter object that counts items of arbitrary types in a string, an array, or an iterable
9+ * in a manner that is similar to Python. Implementation uses the JS map data structure.
10+ *
11+ * @param iterable {string|any[]|Generator} An arbitrary iterable collection, be it an
12+ * array, a string or a generator. Requires the {@link Symbol.iterator} property.
13+ * @returns {CollectionCounter } The counter that tracks how many items are there.
14+ */
15+ constructor ( iterable ) {
16+ if ( ! new . target ) {
17+ return new CollectionCounter ( iterable ) ;
18+ }
19+ super ( ) ;
20+ for ( let item of iterable ) {
21+ super . set ( item , this . get ( item ) + 1 ) ;
22+ }
23+ }
24+
25+ /**
26+ * Get how many items are there in the collection.
27+ *
28+ * @param item The key to get the count of the item.
29+ * @returns {number } 0 if the item is not present in the original iterable value.
30+ */
31+ get ( item ) {
32+ const quantity = super . get ( item ) ;
33+ if ( quantity === undefined ) {
34+ return 0 ;
35+ } else {
36+ return quantity ;
37+ }
38+ }
39+
40+ set ( ) {
41+ throw new Error ( "This counter is not supposed to be modified!" ) ;
42+ }
43+ }
44+
45+ const stringCounter = new CollectionCounter ( "zebra duck elephant kitten bat" ) ;
46+ const arrayCounter = new CollectionCounter ( [
47+ 1 , 4 , 2 , 5 , 7 , 4 , 2 , 6 , 3 , 1 ,
48+ 5 , 3 , 6 , 2 , 7 , 9 , 7 , 8 , 6 , 8 ,
49+ 5 , 3 , 1 , 6 , 4 , 8 , 4 , 4 , 7 , 0
50+ ] ) ;
51+ console . log ( stringCounter ) ;
52+ console . log ( arrayCounter ) ;
0 commit comments