โจBag
keeps track of items and its count.
JS โฉ value โฉ object โฉ class โฉ example โฉ Bag
create a new class not by subclassing, but instead by wrapping or โcomposingโ other classes, this delegation approach is often called โcompositionโ.
// โญ๏ธ Bag
// ------------------------------------------------
// create new class by delegation ("composition")
// ------------------------------------------------
// โข .totalCount : total items count
// โข .items : all (different) items (iterator)
// โข .counts : all counts (iterator)
// โข .entries : all item/count pairs (iterator)
// ------------------------------------------------
// โข .count(item): item count
// โข .has(item) : check if bag has item.
// โข .put(item, [count]) : put item in bag.
// โข .take(item, [count]) : take item from bag if exists.
class Bag {
// private map
#map = new Map();
// Set-like methods
has(item) { return this.count(item) > 0 }
// ----------------------
// iterations
// ----------------------
get items() { return this.#map.keys() } // iterator (for items)
get counts() { return this.#map.values() } // iterator (for counts)
get entries() { return this.#map.entries() } // iterator (item/count pairs)
[Symbol.iterator]() { return this.entries }
// ----------------------
// bag operations
// ----------------------
// item count
count(item) {
return this.#map.get(item) ?? 0;
}
// total count
get totalCount() {
return Array.from(this.counts)
.reduce((result, value) => result + value, 0);
}
// put item(s) into bag
put(item, count = 1) {
this.#map.set(item, this.count(item) + count);
return this; // for chaining
}
// take item(s) from bag
take(item, count = 1) {
const left = this.count(item);
if (left > count) {
this.#map.set(item, left - count);
} else if (left <= count) {
this.#map.delete(item);
}
return this; // for chaining
}
}
// export
module.exports = Bag;
const Bag = require('./Bag.js');
// test run
const bag = new Bag();
bag
.put('apple', 2)
.put('egg', 3)
.put('stone')
.take('egg', 2);
// test iterator
for (const [item, count] of bag) {
log(`${item}: ${count}`); // apple: 2, egg: 1, stone: 1
}
// โญ log
[
bag.has('apple'), // true
bag.has('fish'), // false
bag.count('fish'), // 0
bag.totalCount, // 4
bag.entries, // [ 'apple', 2 ], [ 'egg', 1 ], [ 'stone', 1 ]
].forEach(x => log(x));
Last updated