如何在JavaScript中计算多个数组的交集?[equals:function]是什么意思?
我知道,但是所有的解决方案都假定数组的数量是两个,这在我的例子中是不确定的 我在包含数组的数据的页面上有div。我想找到所有数组的公共值。我不知道我将提前拥有多少个div/数组。计算所有数组通用值的最佳方法是什么如何在JavaScript中计算多个数组的交集?[equals:function]是什么意思?,javascript,arrays,Javascript,Arrays,我知道,但是所有的解决方案都假定数组的数量是两个,这在我的例子中是不确定的 我在包含数组的数据的页面上有div。我想找到所有数组的公共值。我不知道我将提前拥有多少个div/数组。计算所有数组通用值的最佳方法是什么 var array1 = ["Lorem", "ipsum", "dolor"]; var array2 = ["Lorem", "ipsum", "quick", "brown", "foo"]; var array3 = ["Jumps", "Over", "Lazy", "Lor
var array1 = ["Lorem", "ipsum", "dolor"];
var array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
var array3 = ["Jumps", "Over", "Lazy", "Lorem"];
var array4 = [1337, 420, 666, "Lorem"];
//Result should be ["Lorem"];
我在别处找到了另一个解决方案,使用underline.js
var arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];
_.intersection.apply(_, arrayOfArrays)
//Result is [43]
我已经在我的末端用简单的虚拟数据测试过了,它似乎是有效的。但出于某种原因,我正在生成的一些数组(包含简单字符串)也自动包含一个附加值“equals:function”:
每当我在数组上使用underline.js交集方法时,我总是在开发工具中获得[equals:function],而不是-如果所有数组都使用“Dummy3”-[“Dummy3”]
So TL;DR是否有另一种适合我的阵列相交解决方案?有人能解释一下这里的[equals:function]是什么意思吗?当我在dev工具中展开该项时,它会生成一个空数组和数组上可用的方法列表(pop、push、shift等),但这些方法都会淡出,而equals:function会高亮显示 我为此编写了一个助手函数:
function intersection() {
var result = [];
var lists;
if(arguments.length === 1) {
lists = arguments[0];
} else {
lists = arguments;
}
for(var i = 0; i < lists.length; i++) {
var currentList = lists[i];
for(var y = 0; y < currentList.length; y++) {
var currentValue = currentList[y];
if(result.indexOf(currentValue) === -1) {
var existsInAll = true;
for(var x = 0; x < lists.length; x++) {
if(lists[x].indexOf(currentValue) === -1) {
existsInAll = false;
break;
}
}
if(existsInAll) {
result.push(currentValue);
}
}
}
}
return result;
}
或者像这样:
intersection(array1, array2, array3, array4); //["Lorem"]
intersection([array1, array2, array3, array4]); //["Lorem"]
完整代码
更新1
使用
过滤器的一个稍微小一些的实现
使用_lodash的代码运行良好
正如你用小提琴所说:
此代码:
var arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];
var a = _.intersection.apply(_, arrayOfArrays);
console.log(a);
console.log(a.length);
将有以下输出:
[42]
1
也许你看到了
等于:函数
因为您正在使用某种调试器
尝试使用
console.log
打印数组,结果只有42个。如果您想使用一些递归和新的ES2015语法,这可以非常简洁地完成:
const array1=[“Lorem”、“ipsum”、“dolor”];
常量数组2=[“Lorem”、“ipsum”、“quick”、“brown”、“foo”];
常量数组3=[“跳跃”、“越过”、“懒惰”、“知识”];
常量数组4=[1337420666,“Lorem”];
常数阵列法拉利=[[423423232343],[1323,431313],[23,34,43];
//过滤器xs,其中,对于给定的x,y中存在一些y,其中y==x。
常量intersect2=(xs,ys)=>xs.filter(x=>ys.some(y=>y==x));
//当只剩下一个数组时,返回它(终止条件
//(递归的一部分)。否则首先找到第一个的交点
//两个数组(相交2),然后为该结果重复整个过程
//与其余阵列组合(相交)。因此,数组的数量
//作为参数传递给intersect每次减少一个,直到
//只剩下一个阵列。
const intersect=(xs,ys,…rest)=>ys==未定义?xs:intersect(intersect2(xs,ys),…rest);
日志(intersect(array1,array2,array3,array4));
console.log(intersect(…arrayOfArrays));
//或者,用旧币,
var intersect2ES5=函数(xs,ys){
返回xs.filter(函数(x){
返回y.some(函数(y){
返回y==x;
});
});
};
//从上面稍微改变一下,取单个数组,
//这与Q中的underline.js方法相匹配,无论如何都更好。
var INTERSES5=函数(zss){
var xs=zss[0];
var ys=zss[1];
var rest=zss.slice(2);
如果(ys==未定义){
返回xs;
}
返回交点5([intersect2ES5(xs,ys)]。concat(rest));
};
log(intersectES5([array1,array2,array3,array4]);
控制台日志(交叉点5(阵列射线))代码>对于将来对此感到困惑的人
_.intersection.apply(_, arrayOfArrays)
事实上,这是最优雅的方法。但是:
var arrayOfArrays = [[43, 34343, 23232], [43, 314159, 343], [43, 243]];
arrayOfArrays = _.intersection.apply(_, arrayOfArrays);
不行!必须做
var differentVariableName = _.intersection.apply(_,arrayOfArrays);
洛达斯纯:
_.keys(_.pickBy(_.groupBy(_.flatten(arrays)), function (e) {return e.length > 1}))
带普通js的Lodash:
var elements = {}, duplicates = {};
_.each(arrays, function (array) {
_.each(array, function (element) {
if (!elements[element]) {
elements[element] = true;
} else {
duplicates[element] = true;
}
});
});
_.keys(duplicates);
通过综合几位贡献者的想法和最新的ES6 Goods,我得出了以下结论:
const array1=[“Lorem”、“ipsum”、“dolor”];
常量数组2=[“Lorem”、“ipsum”、“quick”、“brown”、“foo”];
常量数组3=[“跳跃”、“越过”、“懒惰”、“知识”];
常量数组4=[1337420666,“Lorem”];
Array.prototype.intersect=函数intersect(a,…b){
常数c=函数(a,b){
b=新的一组(b);
返回a.filter((a)=>b.has(a));
};
returnundefined==a?this:intersect.call(c(this,a),…b);
};
console.log(array1.intersect(array2,array3,array4));
//[“Lorem”]
不依赖es6或任何库的小型递归分治解决方案
它接受一个数组数组,使代码更短,并允许您使用map传递参数
功能交叉点(a){
如果(a.长度>2)
返回交叉点([交叉点(a.slice(0,a.length/2)),交叉点(a.slice(a.length/2)));
如果(a.length==1)
返回[0];
返回[0]。筛选器(函数(项){
返回一个[1]。indexOf(item)!=-1;
});
}
变量列表1=['a','b','c'];
变量列表2=['d','b','e'];
变量列表3=['f','b','e'];
log(交叉点([list1,list2,list3])代码>您可以与和一起使用
var array1=[“Lorem”、“ipsum”、“dolor”],
array2=[“Lorem”、“ipsum”、“quick”、“brown”、“foo”],
数组3=[“跳跃”、“越过”、“懒惰”、“知识”],
数组4=[1337420666,“Lorem”],
数据=[array1,array2,array3,array4],
结果=数据.reduce((a,b)=>a.filter(c=>b.includes(c));
控制台日志(结果)代码>Arg0n的答案很好,但为了防止有人寻找对象数组的交集,我对Arg0n的答案做了一些修改来处理它
function getIntersectedData() {
var lists = [[{a:1,b:2},{a:2,b:2}],[{a:1,b:2},{a:3,b:3}],[{a:1,b:2},{a:4,b:4}]];
var result = [];
for (var i = 0; i < lists.length; i++) {
var currentList = lists[i];
for (var y = 0; y < currentList.length; y++) {
var currentValue = currentList[y];
if (customIndexOf(result,currentValue)) {
var existsInAll = true;
for (var x = 0; x < lists.length; x++) {
if(customIndexOf(lists[x],currentValue)){
existsInAll = false;
break;
}
}
if (existsInAll) {
result.push(currentValue);
}
}
}
return result;
}
}
function customIndexOf(array,value){
var notFind = true;
array.forEach(function(element){
if(element.a === value.a){
notFind = false;
}
});
return notFind;
}
函数getIntersectedData(){
变量列表=[{a:1,b:2},{a:2,b:2}],{a:1,b:2},{a:3,b:3}],{a:1,b:2},{a:4,b:4}];
var结果=[];
对于(变量i=0;ifunction getIntersectedData() {
var lists = [[{a:1,b:2},{a:2,b:2}],[{a:1,b:2},{a:3,b:3}],[{a:1,b:2},{a:4,b:4}]];
var result = [];
for (var i = 0; i < lists.length; i++) {
var currentList = lists[i];
for (var y = 0; y < currentList.length; y++) {
var currentValue = currentList[y];
if (customIndexOf(result,currentValue)) {
var existsInAll = true;
for (var x = 0; x < lists.length; x++) {
if(customIndexOf(lists[x],currentValue)){
existsInAll = false;
break;
}
}
if (existsInAll) {
result.push(currentValue);
}
}
}
return result;
}
}
function customIndexOf(array,value){
var notFind = true;
array.forEach(function(element){
if(element.a === value.a){
notFind = false;
}
});
return notFind;
}
function getArraysIntersection(list1, list2, ...otherLists) {
const result = [];
for (let i = 0; i < list1.length; i++) {
let item1 = list1[i];
let found = false;
for (var j = 0; j < list2.length && !found; j++) {
found = item1 === list2[j];
}
if (found === true) {
result.push(item1);
}
}
if (otherLists.length) {
return getArraysIntersection(result, otherLists.shift(), ...otherLists);
}
else {
return result;
}
}
const intersect = (arrayA, arrayB) => {
return arrayA.filter(elem => arrayB.includes(elem));
};
const intersectAll = (...arrays) => {
if (!Array.isArray(arrays) || arrays.length === 0) return [];
if (arrays.length === 1) return arrays[0];
return intersectAll(intersect(arrays[0], arrays[1]), ...arrays.slice(2));
};
arrays[0].filter(elem => arrays.every(array => array.includes(elem)))
arrays?[0].filter(elem => arrays.every(array => array.includes(elem))) ?? []
const intersect_lists = (lists) => {
const results = []
const lookup = new Map()
lists.map((list, idx) => {
list.map((element) => {
const count = lookup.get(element) || 0
if(count === idx) {
lookup.set(element, 1 + count)
} else {
lookup.delete(element)
}
})
})
// only elements present in all lists will have
// their respective counter equllling the total number of lists
Array.from(lookup.keys()).map((key) => {
if(lookup.get(key) === lists.length) {
results.push(key)
}
})
return results
}
lists.sort((l1, l2) => l1.length - l2.length).map((list, idx) => { ... })