RosettaCodeData/Task/Symmetric-difference/JavaScript/symmetric-difference-3.js

67 lines
1.5 KiB
JavaScript

((a, b) => {
'use strict';
let // UNION AND DIFFERENCE
// union :: [a] -> [a] -> [a]
union = (xs, ys) => unionBy((a, b) => a === b, xs, ys),
// difference :: [a] -> [a] -> [a]
difference = (xs, ys) =>
ys.reduce((a, y) =>
a.indexOf(y) !== -1 ? (
delete_(y, a)
) : a.concat(y), xs),
// GENERAL PRIMITIVES
// unionBy :: (a -> a -> Bool) -> [a] -> [a] -> [a]
unionBy = (f, xs, ys) => {
let sx = nubBy(f, xs),
sy = nubBy(f, ys);
return sx.concat(
sx
.reduce(
(a, x) => deleteBy(f, x, a),
sy
)
)
},
// deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
deleteBy = (f, x, xs) =>
xs.reduce((a, y) => f(x, y) ? a : a.concat(y), []),
// delete_ :: a -> [a] -> [a]
delete_ = (x, xs) =>
deleteBy((a, b) => a === b, x, xs),
// nubBy :: (a -> a -> Bool) -> [a] -> [a]
nubBy = (f, xs) => {
let x = (xs.length ? xs[0] : undefined);
return x !== undefined ? [x].concat(
nubBy(f, xs.slice(1)
.filter(y => !f(x, y))
)
) : [];
};
// 'SYMMETRIC DIFFERENCE'
return union(
difference(a, b),
difference(b, a)
);
})(
["John", "Serena", "Bob", "Mary", "Serena"],
["Jim", "Mary", "John", "Jim", "Bob"]
);