/**
* @module set_utils
* @description A set of utilities for performing set operations on arrays (as if they were sets).
* All the methods will also take sets.
*/
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
// These versions can also take arrays will return the same type as they are given (sets or
// arrays).
export function toSet(value) {
return value instanceof Set ? [true, value] : [false, new Set(value)];
}
/**
* Returns an array with elements in both of the arrays or sets.
*
* @param {Array|Set} A the first array or set
* @param {Array|Set} B the second array or set
* @returns {Array|Set} an array or set with unique values only (matching the type of the argument).
*/
export function intersection(a, b) {
const [isSet, setA] = toSet(a);
const [, setB] = toSet(b);
const intersection = new Set();
for (let elem of setB) {
if (setA.has(elem)) {
intersection.add(elem);
}
}
return isSet ? intersection : Array.from(intersection);
}
/**
* Returns an array with elements in one of the two sets, but not both.
*
* @param {Array|Set} A the first array (a set is OK but this method won't do anything)
* @param {Array|Set} B the second array (a set is OK but this method won't do anything)
* @returns {Array|Set} an array or set with unique values only (matching the type of the argument).
*/
export function difference(a, b) {
const [isSet, setA] = toSet(a);
const [, setB] = toSet(b);
const difference = new Set(setA);
for (let elem of setB) {
difference.delete(elem);
}
return isSet ? difference : Array.from(difference);
}
/**
* Returns an array with only the unique values in the source array.
*
* @param {Array|Set} input an array (a set is OK but this method won't do anything)
* @returns {Array|Set} an array or set with unique values only (matching the type of the argument).
*/
export function unique(array) {
const [isSet, set] = toSet(array);
return isSet ? array : Array.from(set);
}