diff --git a/src/__tests__/map.test.ts b/src/__tests__/map.test.ts index 58d51f5..cd99f7d 100644 --- a/src/__tests__/map.test.ts +++ b/src/__tests__/map.test.ts @@ -259,7 +259,7 @@ describe('DeepMap', () => { }); describe('union method', () => { - it('the union of two maps contains all unique keys and associated values', async () => { + it('the union of two maps contains all key-value pairs from first map and any unique keys from second map', async () => { const map1 = new DeepMap([ [new K('1'), new V('1')], [new K('2'), new V('2')], @@ -293,19 +293,19 @@ describe('DeepMap', () => { }); describe('intersection method', () => { - it('the intersection of two maps contains all shared keys and associated values', async () => { + it('the intersection of two maps contains all shared key-value pairs', async () => { const map1 = new DeepMap([ [new K('1'), new V('1')], [new K('2'), new V('2')], + [new K('3'), new V('3')], ]); const map2 = new DeepMap([ - [new K('2'), new V('999')], - [new K('3'), new V('3')], + [new K('1'), new V('1')], + [new K('2'), new V('999')], // same key but different value -- not a match + [new K('4'), new V('4')], ]); const intersectionMap = map1.intersection(map2); - expect([...intersectionMap.entries()]).toStrictEqual([ - [new K('2'), new V('2')], // value for common key is the value from the caller - ]); + expect([...intersectionMap.entries()]).toStrictEqual([[new K('1'), new V('1')]]); }); it('the intersection of equal maps is the same as either input', async () => { @@ -325,18 +325,21 @@ describe('DeepMap', () => { }); describe('difference method', () => { - it('the difference of two maps contains all keys from first map not in second', async () => { + it('the difference of two maps contains all key-value pairs from first map not in second', async () => { const map1 = new DeepMap([ [new K('1'), new V('1')], [new K('2'), new V('2')], + [new K('3'), new V('3')], ]); const map2 = new DeepMap([ - [new K('2'), new V('999')], - [new K('3'), new V('3')], + [new K('1'), new V('1')], + [new K('2'), new V('999')], // same key but different value -- not a match + [new K('4'), new V('4')], ]); const differenceMap = map1.difference(map2); expect([...differenceMap.entries()]).toStrictEqual([ - [new K('1'), new V('1')], // value for common key is the value from the caller + [new K('2'), new V('2')], + [new K('3'), new V('3')], ]); }); diff --git a/src/map.ts b/src/map.ts index 6bb30de..3a4e450 100644 --- a/src/map.ts +++ b/src/map.ts @@ -125,6 +125,7 @@ export class DeepMap extends Map implements Compar } /** + * @param other the map to compare against * @returns true if the entries of `other` are the same as this map */ equals(other: this): boolean { @@ -132,37 +133,42 @@ export class DeepMap extends Map implements Compar } /** + * @param other the map to compare against * @returns true if the entries of `other` are all contained in this map */ contains(other: this): boolean { - return [...other.entries()].every(([otherKey, otherVal]) => { - const thisVal = this.get(otherKey); - return thisVal !== undefined && this.normalizeValue(thisVal) === this.normalizeValue(otherVal); - }); + return [...other.entries()].every(([key, val]) => this.keyValuePairIsPresentIn(key, val, this)); } /** + * @param other the map to compare against * @returns a new map whose keys are the union of keys between `this` and `other` maps. * - * NOTE: If both maps prescribe the same key, the value from `this` will be retained. + * NOTE: If both maps prescribe the same key, the key-value pair from `this` will be retained. */ union(other: this): DeepMap { return new DeepMap([...other.entries(), ...this.entries()], this.options); } /** - * @returns a new map containing all key-value pairs in `this` whose keys are also in `other`. + * @param other the map to compare against + * @returns a new map containing all key-value pairs in `this` that are also present in `other`. */ intersection(other: this): DeepMap { - const intersectingPairs = [...this.entries()].filter(([key, _value]) => other.has(key)); + const intersectingPairs = [...this.entries()].filter(([key, val]) => + this.keyValuePairIsPresentIn(key, val, other) + ); return new DeepMap(intersectingPairs, this.options); } /** - * @returns a new map containing all key-value pairs in `this` whose keys are not also in `other`. + * @param other the map to compare against + * @returns a new map containing all key-value pairs in `this` that are not present in `other`. */ difference(other: this): DeepMap { - const differencePairs = [...this.entries()].filter(([key, _value]) => !other.has(key)); + const differencePairs = [...this.entries()].filter( + ([key, val]) => !this.keyValuePairIsPresentIn(key, val, other) + ); return new DeepMap(differencePairs, this.options); } @@ -175,4 +181,12 @@ export class DeepMap extends Map implements Compar protected normalizeValue(input: V): Normalized { return this.normalizer.normalizeValue(input); } + + /** + * @returns true if the key is present in the provided map w/ the specified value + */ + private keyValuePairIsPresentIn(key: K, val: V, mapToCheck: this): boolean { + const checkVal = mapToCheck.get(key); + return checkVal !== undefined && this.normalizeValue(checkVal) === this.normalizeValue(val); + } }