Otro enfoque indexado capaz de procesar cualquier cantidad de matrices a la vez:
// Calculate intersection of multiple array or object values.
function intersect (arrList) {
var arrLength = Object.keys(arrList).length;
// (Also accepts regular objects as input)
var index = {};
for (var i in arrList) {
for (var j in arrList[i]) {
var v = arrList[i][j];
if (index[v] === undefined) index[v] = 0;
index[v]++;
};
};
var retv = [];
for (var i in index) {
if (index[i] == arrLength) retv.push(i);
};
return retv;
};
Funciona solo para valores que pueden evaluarse como cadenas y debe pasarlos como una matriz como:
intersect ([arr1, arr2, arr3...]);
... pero acepta objetos de forma transparente como parámetro o como cualquiera de los elementos que se van a intersectar (siempre devuelve una matriz de valores comunes). Ejemplos:
intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]
EDITAR: Acabo de notar que esto es, en cierto modo, un poco defectuoso.
Es decir: lo codifiqué pensando que las matrices de entrada por sí mismas no pueden contener repeticiones (como el ejemplo provisto no lo hace).
Pero si las matrices de entrada contienen repeticiones, eso produciría resultados incorrectos. Ejemplo (usando la implementación a continuación):
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]
Afortunadamente, esto es fácil de solucionar simplemente agregando indexación de segundo nivel. Es decir:
Cambio:
if (index[v] === undefined) index[v] = 0;
index[v]++;
por:
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
...y:
if (index[i] == arrLength) retv.push(i);
por:
if (Object.keys(index[i]).length == arrLength) retv.push(i);
Ejemplo completo:
// Calculate intersection of multiple array or object values.
function intersect (arrList) {
var arrLength = Object.keys(arrList).length;
// (Also accepts regular objects as input)
var index = {};
for (var i in arrList) {
for (var j in arrList[i]) {
var v = arrList[i][j];
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
};
};
var retv = [];
for (var i in index) {
if (Object.keys(index[i]).length == arrLength) retv.push(i);
};
return retv;
};
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]); // [ '1' ]