Ein funktionaler Ansatz mit ES2015
Nach dem funktionalen Ansatz wird ein union
von zwei Array
s ist einfach die Zusammensetzung von concat
y filter
. Um eine optimale Leistung zu gewährleisten, greifen wir auf die native Set
Datentyp, der für die Suche nach Eigenschaften optimiert ist.
Wie auch immer, die Schlüsselfrage in Verbindung mit einem union
Funktion ist, wie Duplikate zu behandeln sind. Die folgenden Permutationen sind möglich:
Array A + Array B
[unique] + [unique]
[duplicated] + [unique]
[unique] + [duplicated]
[duplicated] + [duplicated]
Die ersten beiden Permutationen sind mit einer einzigen Funktion leicht zu handhaben. Die letzten beiden sind jedoch komplizierter, da man sie nicht verarbeiten kann, solange man sich auf Set
Nachschlagen. Seit der Umstellung auf die einfache alte Object
Die folgende Implementierung ignoriert einfach die dritte und vierte Permutation, da die Suche nach den Eigenschaften einen erheblichen Leistungsverlust zur Folge hätte. Sie müssten eine separate Version von union
um sie zu unterstützen.
// small, reusable auxiliary functions
const comp = f => g => x => f(g(x));
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// de-duplication
const dedupe = comp(afrom) (createSet);
// the actual union function
const union = xs => ys => {
const zs = createSet(xs);
return concat(xs) (
filter(x => zs.has(x)
? false
: zs.add(x)
) (ys));
}
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];
// here we go
console.log( "unique/unique", union(dedupe(xs)) (ys) );
console.log( "duplicated/unique", union(xs) (ys) );
Von hier an wird es trivial, eine unionn
Funktion, die eine beliebige Anzahl von Arrays akzeptiert (inspiriert durch die Kommentare von Naomik):
// small, reusable auxiliary functions
const uncurry = f => (a, b) => f(a) (b);
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
// union and unionn
const union = xs => ys => {
const zs = createSet(xs);
return concat(xs) (
filter(x => zs.has(x)
? false
: zs.add(x)
) (ys));
}
const unionn = (head, ...tail) => foldl(union) (head) (tail);
// mock data
const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];
const zs = [0,1,2,3,4,5,6,7,8,9];
// here we go
console.log( unionn(xs, ys, zs) );
Es stellt sich heraus unionn
ist nur foldl
(alias Array.prototype.reduce
), die die union
als dessen Reduktionsmittel. Hinweis: Da die Implementierung keinen zusätzlichen Akkumulator verwendet, wird sie einen Fehler auslösen, wenn Sie sie ohne Argumente anwenden.