160 lines
4.7 KiB
JavaScript
Executable File
160 lines
4.7 KiB
JavaScript
Executable File
/**
|
|
* @license
|
|
* Copyright The Closure Library Authors.
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @fileoverview Helper methods that operate on Map-like objects (e.g. ES6
|
|
* Maps).
|
|
*/
|
|
|
|
goog.module('goog.collections.maps');
|
|
goog.module.declareLegacyNamespace();
|
|
|
|
/**
|
|
* A MapLike implements the same public interface as an ES6 Map, without tying
|
|
* the underlying code directly to the implementation. Any additions to this
|
|
* type should also be present on ES6 Maps.
|
|
* @template K,V
|
|
* @record
|
|
*/
|
|
class MapLike {
|
|
constructor() {
|
|
/** @const {number} The number of items in this map. */
|
|
this.size;
|
|
}
|
|
|
|
/**
|
|
* @param {K} key The key to set in the map.
|
|
* @param {V} val The value to set for the given key in the map.
|
|
*/
|
|
set(key, val) {};
|
|
|
|
/**
|
|
* @param {K} key The key to retrieve from the map.
|
|
* @return {V|undefined} The value for this key, or undefined if the key is
|
|
* not present in the map.
|
|
*/
|
|
get(key) {};
|
|
|
|
/**
|
|
* @return {!IteratorIterable<K>} An ES6 Iterator that iterates over the keys
|
|
* in the map.
|
|
*/
|
|
keys() {};
|
|
|
|
/**
|
|
* @return {!IteratorIterable<V>} An ES6 Iterator that iterates over the
|
|
* values in the map.
|
|
*/
|
|
values() {};
|
|
|
|
/**
|
|
* @param {K} key The key to check.
|
|
* @return {boolean} True iff this key is present in the map.
|
|
*/
|
|
has(key) {};
|
|
}
|
|
exports.MapLike = MapLike;
|
|
|
|
/**
|
|
* Iterates over each entry in the given entries and sets the entry in
|
|
* the map, overwriting any existing entries for the key.
|
|
* @param {!MapLike<K,V>} map The map to set entries on.
|
|
* @param {?Iterable<!Array<K|V>>} entries The iterable of entries. This
|
|
* iterable should really be of type Iterable<Array<[K,V]>>, but the tuple
|
|
* type is not representable in the Closure Type System.
|
|
* @template K,V
|
|
*/
|
|
function setAll(map, entries) {
|
|
if (!entries) return;
|
|
for (const [k, v] of entries) {
|
|
map.set(k, v);
|
|
}
|
|
}
|
|
exports.setAll = setAll;
|
|
|
|
/**
|
|
* Determines if a given map contains the given value, optionally using
|
|
* a custom comparison function.
|
|
* @param {!MapLike<?,V1>} map The map whose values to check.
|
|
* @param {V2} val The value to check for.
|
|
* @param {(function(V1,V2): boolean)=} valueEqualityFn The comparison function
|
|
* used to determine if the given value is equivalent to any of the values
|
|
* in the map. If no function is provided, defaults to strict equality
|
|
* (===).
|
|
* @return {boolean} True iff the given map contains the given value according
|
|
* to the comparison function.
|
|
* @template V1,V2
|
|
*/
|
|
function hasValue(map, val, valueEqualityFn = defaultEqualityFn) {
|
|
for (const v of map.values()) {
|
|
if (valueEqualityFn(v, val)) return true;
|
|
}
|
|
return false;
|
|
}
|
|
exports.hasValue = hasValue;
|
|
|
|
/** @const {function(?,?): boolean} */
|
|
const defaultEqualityFn = (a, b) => a === b;
|
|
|
|
/**
|
|
* Compares two maps using their public APIs to determine if they have
|
|
* equal contents, optionally using a custom comparison function when comaring
|
|
* values.
|
|
* @param {!MapLike<K,V1>} map The first map
|
|
* @param {!MapLike<K,V2>} otherMap The other map
|
|
* @param {(function(V1,V2): boolean)=} valueEqualityFn The comparison function
|
|
* used to determine if the values obtained from each map are equivalent. If
|
|
* no function is provided, defaults to strict equality (===).
|
|
* @return {boolean}
|
|
* @template K,V1,V2
|
|
*/
|
|
function equals(map, otherMap, valueEqualityFn = defaultEqualityFn) {
|
|
if (map === otherMap) return true;
|
|
if (map.size !== otherMap.size) return false;
|
|
for (const key of map.keys()) {
|
|
if (!otherMap.has(key)) return false;
|
|
if (!valueEqualityFn(map.get(key), otherMap.get(key))) return false;
|
|
}
|
|
return true;
|
|
}
|
|
exports.equals = equals;
|
|
|
|
/**
|
|
* Returns a new ES6 Map in which all the keys and values from the
|
|
* given map are interchanged (keys become values and values become keys). If
|
|
* multiple keys in the given map to the same value, the resulting value in the
|
|
* transposed map is implementation-dependent.
|
|
*
|
|
* It acts very similarly to {goog.object.transpose(Object)}.
|
|
* @param {!MapLike<K,V>} map The map to transpose.
|
|
* @return {!Map<V,K>} A transposed version of the given map.
|
|
* @template K,V
|
|
*/
|
|
function transpose(map) {
|
|
const /** !Map<V,K> */ transposed = new Map();
|
|
for (const key of map.keys()) {
|
|
const val = map.get(key);
|
|
transposed.set(val, key);
|
|
}
|
|
return transposed;
|
|
}
|
|
exports.transpose = transpose;
|
|
|
|
/**
|
|
* ToObject returns a new object whose properties are the keys from the Map.
|
|
* @param {!MapLike<K,V>} map The map to convert into an object.
|
|
* @return {!Object<K,V>} An object representation of the Map.
|
|
* @template K,V
|
|
*/
|
|
function toObject(map) {
|
|
const /** !Object<K,V> */ obj = {};
|
|
for (const key of map.keys()) {
|
|
obj[key] = map.get(key);
|
|
}
|
|
return obj;
|
|
}
|
|
exports.toObject = toObject;
|