用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
用javascript实现数组交叉的最简单、无库代码是什么?我想写
intersection([1,2,3], [2,3,4,5])
并获得
[2, 3]
当前回答
另一种可以同时处理任意数量数组的索引方法:
// 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"]
编辑:我只是注意到,这是,在某种程度上,有点bug。
也就是说:我在编码时认为输入数组本身不能包含重复(正如所提供的示例那样)。
但如果输入数组恰好包含重复,就会产生错误的结果。示例(使用下面的实现):
intersect ([[1, 3, 4, 6, 3], [1, 8, 99]]);
// Expected: [ '1' ]
// Actual: [ '1', '3' ]
幸运的是,这很容易通过添加二级索引来解决。那就是:
变化:
if (index[v] === undefined) index[v] = 0;
index[v]++;
by:
if (index[v] === undefined) index[v] = {};
index[v][i] = true; // Mark as present in i input.
,:
if (index[i] == arrLength) retv.push(i);
by:
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' ]
其他回答
我使用地图甚至对象可以使用。
//find intersection of 2 arrs
const intersections = (arr1,arr2) => {
let arrf = arr1.concat(arr2)
let map = new Map();
let union = [];
for(let i=0; i<arrf.length; i++){
if(map.get(arrf[i])){
map.set(arrf[i],false);
}else{
map.set(arrf[i],true);
}
}
map.forEach((v,k)=>{if(!v){union.push(k);}})
return union;
}
下面是underscore.js的实现:
_.intersection = function(array) {
if (array == null) return [];
var result = [];
var argsLength = arguments.length;
for (var i = 0, length = array.length; i < length; i++) {
var item = array[i];
if (_.contains(result, item)) continue;
for (var j = 1; j < argsLength; j++) {
if (!_.contains(arguments[j], item)) break;
}
if (j === argsLength) result.push(item);
}
return result;
};
来源:http://underscorejs.org/docs/underscore.html部分- 62
“filter”和“indexOf”在IE中的Array上不支持。这个怎么样:
var array1 = [1, 2, 3];
var array2 = [2, 3, 4, 5];
var intersection = [];
for (i in array1) {
for (j in array2) {
if (array1[i] == array2[j]) intersection.push(array1[i]);
}
}
希望这有助于所有版本。
function diffArray(arr1, arr2) {
var newArr = [];
var large = arr1.length>=arr2.length?arr1:arr2;
var small = JSON.stringify(large) == JSON.stringify(arr1)?arr2:arr1;
for(var i=0;i<large.length;i++){
var copyExists = false;
for(var j =0;j<small.length;j++){
if(large[i]==small[j]){
copyExists= true;
break;
}
}
if(!copyExists)
{
newArr.push(large[i]);
}
}
for(var i=0;i<small.length;i++){
var copyExists = false;
for(var j =0;j<large.length;j++){
if(large[j]==small[i]){
copyExists= true;
break;
}
}
if(!copyExists)
{
newArr.push(small[i]);
}
}
return newArr;
}
.reduce生成地图,.filter找到交叉路口。.filter中的Delete允许我们将第二个数组视为唯一的集合。
function intersection (a, b) {
var seen = a.reduce(function (h, k) {
h[k] = true;
return h;
}, {});
return b.filter(function (k) {
var exists = seen[k];
delete seen[k];
return exists;
});
}
我发现这种方法很容易解释。它在常数时间内运行。