Еще один индексированный подход, способный обрабатывать любое количество массивов одновременно:
// 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;
};
Он работает только для значений, которые могут быть оценены как строки, и вы должны передать их как массив, например:
intersect ([arr1, arr2, arr3...]);
... но он прозрачно принимает объекты как параметр или как любой из элементов, которые должны быть пересечены (всегда возвращает массив общих значений). Примеры:
intersect ({foo: [1, 2, 3, 4], bar: {a: 2, j:4}}); // [2, 4]
intersect ([{x: "hello", y: "world"}, ["hello", "user"]]); // ["hello"]
РЕДАКТИРОВАТЬ: я только заметил, что это, в некотором смысле, немного глючит.
То есть: я кодировал его, думая, что входные массивы не могут содержать повторения (как в приведенном примере этого не происходит).
Но если входные массивы содержат повторения, это приведет к неверным результатам. Пример (используя приведенную ниже реализацию):
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]
К счастью, это легко исправить, просто добавив индексирование второго уровня. Это:
Изменить:
if (index[v] === undefined) index[v] = 0;
index[v]++;
по:
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
...а также:
if (index[i] == arrLength) retv.push(i);
по:
if (Object.keys(index[i]).length == arrLength) retv.push(i);
Полный пример:
// 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' ]