Bag

keeps track of items and its count.

JSvalueobjectclassexample ⟩ 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;

Last updated