/** * @author d98762625 [d98762625@gmail.com] * @copyright Crown Copyright 2018 * @license Apache-2.0 */ import Utils from "../Utils.mjs"; import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; /** * Set Symmetric Difference operation */ class SymmetricDifference extends Operation { /** * Symmetric Difference constructor */ constructor() { super(); this.name = "Symmetric Difference"; this.module = "Default"; this.description = "Calculates the symmetric difference of two sets."; this.infoURL = "https://wikipedia.org/wiki/Symmetric_difference"; this.inputType = "string"; this.outputType = "string"; this.args = [ { name: "Sample delimiter", type: "binaryString", value: Utils.escapeHtml("\\n\\n") }, { name: "Item delimiter", type: "binaryString", value: "," }, ]; } /** * Validate input length * * @param {Object[]} sets * @throws {Error} if not two sets */ validateSampleNumbers(sets) { if (!sets || (sets.length !== 2)) { throw new OperationError("Incorrect number of sets, perhaps you need to modify the sample delimiter or add more samples?"); } } /** * Run the difference operation * * @param {string} input * @param {Object[]} args * @returns {string} * @throws {OperationError} */ run(input, args) { [this.sampleDelim, this.itemDelimiter] = args; const sets = input.split(this.sampleDelim); this.validateSampleNumbers(sets); return this.runSymmetricDifference(...sets.map(s => s.split(this.itemDelimiter))); } /** * Get elements in set a that are not in set b * * @param {Object[]} a * @param {Object[]} b * @returns {Object[]} */ runSetDifference(a, b) { return a.filter((item) => { return b.indexOf(item) === -1; }); } /** * Get elements of each set that aren't in the other set. * * @param {Object[]} a * @param {Object[]} b * @return {Object[]} */ runSymmetricDifference(a, b) { return this.runSetDifference(a, b) .concat(this.runSetDifference(b, a)) .join(this.itemDelimiter); } } export default SymmetricDifference;