JavaScript中数组交集的最简单代码
在javascript中实现数组交集的最简单,无库代码是什么? 我想写
intersection([1,2,3], [2,3,4,5])
并得到
[2, 3]
#1楼
通过使用.pop而不是.shift可以改善@atk对基元排序数组的实现的性能。
function intersect(array1, array2) {var result = [];// Don't destroy the original arraysvar a = array1.slice(0);var b = array2.slice(0);var aLast = a.length - 1;var bLast = b.length - 1;while (aLast >= 0 && bLast >= 0) {if (a[aLast] > b[bLast] ) {a.pop();aLast--;} else if (a[aLast] < b[bLast] ){b.pop();bLast--;} else /* they're equal */ {result.push(a.pop());b.pop();aLast--;bLast--;}}return result;
}
我使用jsPerf创建了一个基准测试: http ://bit.ly/P9FrZK。 使用.pop的速度大约快三倍。
#2楼
function intersection(A,B){
var result = new Array();
for (i=0; i<A.length; i++) {for (j=0; j<B.length; j++) {if (A[i] == B[j] && $.inArray(A[i],result) == -1) {result.push(A[i]);}}
}
return result;
}
#3楼
我将以最适合我的方式做出贡献:
if (!Array.prototype.intersect){
Array.prototype.intersect = function (arr1) {var r = [], o = {}, l = this.length, i, v;for (i = 0; i < l; i++) {o[this[i]] = true;}l = arr1.length;for (i = 0; i < l; i++) {v = arr1[i];if (v in o) {r.push(v);}}return r;
};
}
#4楼
结合使用Array.prototype.filter
和Array.prototype.indexOf
:
array1.filter(value => -1 !== array2.indexOf(value))
或如评论中建议的vrugtehagel一样 ,您可以使用更新的Array.prototype.includes
来获取更简单的代码:
array1.filter(value => array2.includes(value))
对于较旧的浏览器:
array1.filter(function(n) {return array2.indexOf(n) !== -1;
});
#5楼
- 把它分类
- 从索引0逐一检查,从中创建新数组。
这样的东西,虽然没有很好的测试。
function intersection(x,y){x.sort();y.sort();var i=j=0;ret=[];while(i<x.length && j<y.length){if(x[i]<y[j])i++;else if(y[j]<x[i])j++;else {ret.push(x[i]);i++,j++;}}return ret;
}alert(intersection([1,2,3], [2,3,4,5]));
PS:仅适用于数字和普通字符串的算法,任意对象数组的交集可能不起作用。
#6楼
破坏性似乎最简单,特别是如果我们可以假定输入已排序:
/* destructively finds the intersection of * two arrays in a simple fashion. ** PARAMS* a - first array, must already be sorted* b - second array, must already be sorted** NOTES* State of input arrays is undefined when* the function returns. They should be * (prolly) be dumped.** Should have O(n) operations, where n is * n = MIN(a.length, b.length)*/
function intersection_destructive(a, b)
{var result = [];while( a.length > 0 && b.length > 0 ){ if (a[0] < b[0] ){ a.shift(); }else if (a[0] > b[0] ){ b.shift(); }else /* they're equal */{result.push(a.shift());b.shift();}}return result;
}
由于我们必须跟踪索引,因此非破坏性的头发必须更加复杂。
/* finds the intersection of * two arrays in a simple fashion. ** PARAMS* a - first array, must already be sorted* b - second array, must already be sorted** NOTES** Should have O(n) operations, where n is * n = MIN(a.length(), b.length())*/
function intersect_safe(a, b)
{var ai=0, bi=0;var result = [];while( ai < a.length && bi < b.length ){if (a[ai] < b[bi] ){ ai++; }else if (a[ai] > b[bi] ){ bi++; }else /* they're equal */{result.push(a[ai]);ai++;bi++;}}return result;
}
#7楼
仅使用关联数组怎么样?
function intersect(a, b) {var d1 = {};var d2 = {};var results = [];for (var i = 0; i < a.length; i++) {d1[a[i]] = true;}for (var j = 0; j < b.length; j++) {d2[b[j]] = true;}for (var k in d1) {if (d2[k]) results.push(k);}return results;
}
编辑:
// new version
function intersect(a, b) {var d = {};var results = [];for (var i = 0; i < b.length; i++) {d[b[i]] = true;}for (var j = 0; j < a.length; j++) {if (d[a[j]]) results.push(a[j]);}return results;
}
#8楼
对于仅包含字符串或数字的数组,您可以按照其他一些答案进行排序。 对于任意对象数组的一般情况,我认为您不能避免这样做。 下面将为您提供作为arrayIntersection
参数提供的任意数量的数组的arrayIntersection
:
var arrayContains = Array.prototype.indexOf ?function(arr, val) {return arr.indexOf(val) > -1;} :function(arr, val) {var i = arr.length;while (i--) {if (arr[i] === val) {return true;}}return false;};function arrayIntersection() {var val, arrayCount, firstArray, i, j, intersection = [], missing;var arrays = Array.prototype.slice.call(arguments); // Convert arguments into a real array// Search for common valuesfirstArray = arrays.pop();if (firstArray) {j = firstArray.length;arrayCount = arrays.length;while (j--) {val = firstArray[j];missing = false;// Check val is present in each remaining array i = arrayCount;while (!missing && i--) {if ( !arrayContains(arrays[i], val) ) {missing = true;}}if (!missing) {intersection.push(val);}}}return intersection;
}arrayIntersection( [1, 2, 3, "a"], [1, "a", 2], ["a", 1] ); // Gives [1, "a"];
#9楼
使用jQuery :
var a = [1,2,3];
var b = [2,3,4,5];
var c = $(b).not($(b).not(a));
alert(c);
#10楼
IE 9.0,Chrome,Firefox,Opera的“ indexOf”
function intersection(a,b){var rs = [], x = a.length;while (x--) b.indexOf(a[x])!=-1 && rs.push(a[x]);return rs.sort();}intersection([1,2,3], [2,3,4,5]);
//Result: [2,3]
#11楼
这是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#section-62
#12楼
另一种索引方法能够一次处理任意数量的数组:
// 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' ]
#13楼
在数据上有一些限制,您可以在线性时间内完成!
对于正整数 :使用将值映射到“可见/不可见”布尔值的数组。
function intersectIntegers(array1,array2) { var seen=[],result=[];for (var i = 0; i < array1.length; i++) {seen[array1[i]] = true;}for (var i = 0; i < array2.length; i++) {if ( seen[array2[i]])result.push(array2[i]);}return result;
}
对于对象,有一种类似的技术:取一个虚拟密钥,将其设置为array1中每个元素的“ true”,然后在array2的元素中查找该密钥。 完成后清理。
function intersectObjects(array1,array2) { var result=[];var key="tmpKey_intersect"for (var i = 0; i < array1.length; i++) {array1[i][key] = true;}for (var i = 0; i < array2.length; i++) {if (array2[i][key])result.push(array2[i]);}for (var i = 0; i < array1.length; i++) {delete array1[i][key];}return result;
}
当然,您需要确保密钥之前没有出现,否则您将销毁数据...
#14楼
对此处的最小调整进行细微调整( filter / indexOf解决方案 ),即使用JavaScript对象在数组之一中创建值的索引,会将其从O(N * M)减少为“大概”线性时间。 源1 源2
function intersect(a, b) {var aa = {};a.forEach(function(v) { aa[v]=1; });return b.filter(function(v) { return v in aa; });
}
这不是最简单的解决方案(它比filter + indexOf的代码更多),也不是最快的(可能比intersect_safe()慢一个常数),但似乎是一个很好的平衡。 它具有非常简单的一面,同时提供了良好的性能,并且不需要预先排序的输入。
#15楼
如果您的环境支持ECMAScript 6 Set ,那么这是一种简单有效的方法(请参阅规范链接):
function intersect(a, b) {var setA = new Set(a);var setB = new Set(b);var intersection = new Set([...setA].filter(x => setB.has(x)));return Array.from(intersection);
}
较短,但可读性较低(也没有创建其他交集Set
):
function intersect(a, b) {return [...new Set(a)].filter(x => new Set(b).has(x));
}
每次都避免从b
产生新的Set
:
function intersect(a, b) {var setB = new Set(b);return [...new Set(a)].filter(x => setB.has(x));
}
请注意,使用集时,您只会获得不同的值,因此new Set[1,2,3,3].size
值为3
。
#16楼
我对ES6的贡献。 通常,它会找到一个数组与作为参数提供的不确定数量的数组的交集。
Array.prototype.intersect = function(...a) { return [this,...a].reduce((p,c) => p.filter(e => c.includes(e))); } var arrs = [[0,2,4,6,8],[4,5,6,7],[4,6]], arr = [0,1,2,3,4,5,6,7,8,9]; document.write("<pre>" + JSON.stringify(arr.intersect(...arrs)) + "</pre>");
#17楼
使用Underscore.js或lodash.js
_.intersection( [0,345,324] , [1,0,324] ) // gives [0,324]
#18楼
'use strict' // Example 1 function intersection(a1, a2) { return a1.filter(x => a2.indexOf(x) > -1) } // Example 2 (prototype function) Array.prototype.intersection = function(arr) { return this.filter(x => arr.indexOf(x) > -1) } const a1 = [1, 2, 3] const a2 = [2, 3, 4, 5] console.log(intersection(a1, a2)) console.log(a1.intersection(a2))
#19楼
ES2015的功能性方法
功能方法必须考虑仅使用无副作用的纯函数,而每个副作用仅与一项工作有关。
这些限制增强了所涉及功能的可组合性和可重用性。
// small, reusable auxiliary functions const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); const apply = f => x => f(x); // intersection const intersect = xs => ys => { const zs = createSet(ys); return filter(x => zs.has(x) ? true : false ) (xs); }; // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,3,6,7,8,9]; // run it console.log( intersect(xs) (ys) );
请注意,使用本机Set
类型,具有有利的查找性能。
避免重复
显然,第一个Array
中重复出现的项目将被保留,而第二个Array
被删除重复数据。 这可能是或可能不是所需的行为。 如果您需要唯一的结果,只需将dedupe
应用于第一个参数:
// auxiliary functions const apply = f => x => f(x); const comp = f => g => x => f(g(x)); const afrom = apply(Array.from); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); // intersection const intersect = xs => ys => { const zs = createSet(ys); return filter(x => zs.has(x) ? true : false ) (xs); }; // de-duplication const dedupe = comp(afrom) (createSet); // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,3,6,7,8,9]; // unique result console.log( intersect(dedupe(xs)) (ys) );
计算任意数量Array
的交集
如果要计算任意数量的Array
的intersect
,则只需与foldl
组成intersect
。 这是一个便捷功能:
// auxiliary functions const apply = f => x => f(x); const uncurry = f => (x, y) => f(x) (y); const createSet = xs => new Set(xs); const filter = f => xs => xs.filter(apply(f)); const foldl = f => acc => xs => xs.reduce(uncurry(f), acc); // intersection const intersect = xs => ys => { const zs = createSet(ys); return filter(x => zs.has(x) ? true : false ) (xs); }; // intersection of an arbitrarily number of Arrays const intersectn = (head, ...tail) => foldl(intersect) (head) (tail); // mock data const xs = [1,2,2,3,4,5]; const ys = [0,1,2,3,3,3,6,7,8,9]; const zs = [0,1,2,3,4,5,6]; // run console.log( intersectn(xs, ys, zs) );
#20楼
为简单起见:
// Usage
const intersection = allLists.reduce(intersect, allValues).reduce(removeDuplicates, []);// Implementation
const intersect = (intersection, list) =>intersection.filter(item =>list.some(x => x === item));const removeDuplicates = (uniques, item) =>uniques.includes(item) ? uniques : uniques.concat(item);// Example Data
const somePeople = [bob, doug, jill];
const otherPeople = [sarah, bob, jill];
const morePeople = [jack, jill];const allPeople = [...somePeople, ...otherPeople, ...morePeople];
const allGroups = [somePeople, otherPeople, morePeople];// Example Usage
const intersection = allGroups.reduce(intersect, allPeople).reduce(removeDuplicates, []);intersection; // [jill]
优点:
- 简单的污垢
- 以数据为中心
- 适用于任意数量的列表
- 适用于任意长度的列表
- 适用于任意类型的值
- 适用于任意排序顺序
- 保持形状(任何阵列中的首次出现顺序)
- 尽可能提前退出
- 内存安全,不影响功能/阵列原型
缺点:
- 更高的内存使用率
- 更高的CPU使用率
- 需要了解减少
- 需要了解数据流
您不想将其用于3D引擎或内核工作,但是如果您无法在基于事件的应用程序中运行它,则会遇到更大的问题。
#21楼
.reduce
建设地图,并.filter
找到交集。 delete
内.filter
允许我们把第二阵列,就好像它是一个独特的一套。
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;});
}
我发现这种方法很容易推理。 它以恒定的时间执行。
#22楼
// Return elements of array a that are also in b in linear time: function intersect(a, b) { return a.filter(Set.prototype.has, new Set(b)); } // Example: console.log(intersect([1,2,3], [2,3,4,5]));
我推荐以上简洁的解决方案,该解决方案在大输入量方面胜过其他实现。 如果小投入的性能很重要,请检查以下替代方案。
替代方案和性能比较:
请参阅以下代码段以了解替代实现,并检查https://jsperf.com/array-intersection-comparison以进行性能比较。
function intersect_for(a, b) { const result = []; const alen = a.length; const blen = b.length; for (let i = 0; i < alen; ++i) { const ai = a[i]; for (let j = 0; j < blen; ++j) { if (ai === b[j]) { result.push(ai); break; } } } return result; } function intersect_filter_indexOf(a, b) { return a.filter(el => b.indexOf(el) !== -1); } function intersect_filter_in(a, b) { const map = b.reduce((map, el) => {map[el] = true; return map}, {}); return a.filter(el => el in map); } function intersect_for_in(a, b) { const result = []; const map = {}; for (let i = 0, length = b.length; i < length; ++i) { map[b[i]] = true; } for (let i = 0, length = a.length; i < length; ++i) { if (a[i] in map) result.push(a[i]); } return result; } function intersect_filter_includes(a, b) { return a.filter(el => b.includes(el)); } function intersect_filter_has_this(a, b) { return a.filter(Set.prototype.has, new Set(b)); } function intersect_filter_has_arrow(a, b) { const set = new Set(b); return a.filter(el => set.has(el)); } function intersect_for_has(a, b) { const result = []; const set = new Set(b); for (let i = 0, length = a.length; i < length; ++i) { if (set.has(a[i])) result.push(a[i]); } return result; }
Firefox 53中的结果:
大型阵列(10,000个元素)上的运算/秒:
filter + has (this) 523 (this answer) for + has 482 for-loop + in 279 filter + in 242 for-loops 24 filter + includes 14 filter + indexOf 10
小型阵列(100个元素)上的运算/秒:
for-loop + in 384,426 filter + in 192,066 for-loops 159,137 filter + includes 104,068 filter + indexOf 71,598 filter + has (this) 43,531 (this answer) filter + has (arrow function) 35,588
#23楼
使用ES2015和Sets很短。 接受类似String的类似数组的值,并删除重复项。
let intersection = function(a, b) { a = new Set(a), b = new Set(b); return [...a].filter(v => b.has(v)); }; console.log(intersection([1,2,1,2,3], [2,3,5,4,5,3])); console.log(intersection('ccaabbab', 'addb').join(''));
#24楼
function getIntersection(arr1, arr2){var result = [];arr1.forEach(function(elem){arr2.forEach(function(elem2){if(elem === elem2){result.push(elem);}});});return result;
}getIntersection([1,2,3], [2,3,4,5]); // [ 2, 3 ]
#25楼
除了list1.filter(n => list2.includes(n)) ,这可能是最简单的一个
var list1 = ['bread', 'ice cream', 'cereals', 'strawberry', 'chocolate'] var list2 = ['bread', 'cherry', 'ice cream', 'oats'] function check_common(list1, list2){ list3 = [] for (let i=0; i<list1.length; i++){ for (let j=0; j<list2.length; j++){ if (list1[i] === list2[j]){ list3.push(list1[i]); } } } return list3 } check_common(list1, list2) // ["bread", "ice cream"]
#26楼
如果需要让它处理相交的多个数组:
const intersect = (a, b, ...rest) => { if (rest.length === 0) return [...new Set(a)].filter(x => new Set(b).has(x)); return intersect(a, intersect(b, ...rest)); }; console.log(intersect([1,2,3,4,5], [1,2], [1, 2, 3,4,5], [2, 10, 1])) // [1,2]
#27楼
ES6风格简单的方法。
const intersection = (a, b) => {const s = new Set(b);return a.filter(x => s.has(x));
};
例:
intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
#28楼
而不是使用indexOf,您也可以使用Array.protype.includes 。
function intersection(arr1, arr2) { return arr1.filter((ele => { return arr2.includes(ele); })); } console.log(intersection([1,2,3], [2,3,4,5]));
#29楼
如果第二个数组总是要作为一个集合来处理,则无需在第二个数组的函数内部声明中间变量。
以下解决方案返回在两个数组中均出现的唯一值数组:
const intersection = (a, b) => {b = new Set(b); // recycling variablereturn [...new Set(a)].filter(e => b.has(e));
};console.log(intersection([1, 2, 3, 1, 1], [1, 2, 4])); // Array [ 1, 2 ]
#30楼
如果要使用已接受的答案,但需要支持Internet Explorer,则必须避免使用箭头功能速记注释。 这是编辑过的单行程序,也可以在IE中使用:
// accepted aswer: array1.filter(value => -1 !== array2.indexOf(value));
// IE-supported syntax:
array1.filter(function(value) { return -1 !== array2.indexOf(value) });
#31楼
您可以使用(适用于除IE之外的所有浏览器):
const intersection = array1.filter(element => array2.includes(element));
或IE:
const intersection = array1.filter(element => array2.indexOf(element) !== -1);
JavaScript中数组交集的最简单代码相关推荐
- JavaScript 中call apply 那点简单事
谈谈JavaScript 中call apply 那点简单事 平常是否遇到过call apply 的问题 比如说 怎么利用call.apply来求一个数组中最大或者最小值 如何利用call.apply ...
- JavaScript中数组使用总结
一. 数组的概念 1.1 什么是数组 数组是指的数据的有序列表. 数组中每个值称之为数组的一个元素. 数组中的每个元素都有一个位置,这个位置称之为索引(下标.index).数组的索引是从 0 开始的 ...
- 前端 JavaScript 之『节流』的简单代码实现
前戏 首先,总结一下上一篇文章--<前端 JavaScript 之『防抖』的简单代码实现>的内容:「防抖」就是在高频率触发事件停止触发后,延时执行某个处理逻辑. 防抖虽然在一定程度上对性能 ...
- java中字符串和数组如何比较_[Java教程]javascript中数组和字符串的方法比较
[Java教程]javascript中数组和字符串的方法比较 0 2016-07-19 23:00:05 ×目录[1]可索引 [2]转换 [3]拼接[4]创建[5]位置 前面的话 字符串和数组有很多的 ...
- [乐意黎原创] JavaScript中数组使用总结
原文地址:http://blog.csdn.net/u012468376/article/details/53147098 一. 数组的概念 1.1 什么是数组 数组是指的数据的有序列表. 数组中每个 ...
- python代码大全表解释-Python中顺序表的实现简单代码分享
顺序表python版的实现(部分功能未实现) 结果展示: 代码示例: #!/usr/bin/env python # -*- coding:utf-8 -*- class SeqList(object ...
- html 记住密码 自动登陆,JavaScript登录记住密码操作(超简单代码)
废话不多说了,直接给大家贴代码了,具体代码如下所示: 记住密码 记住密码 window.onload = function(){ var oForm = document.getElementById ...
- JavaScript中数组slice和splice的对比小结
前言 今天重温了一下Javascript,看到了数组的方法,其中有两个比较相似的方法--splice和splice,看着很像,就是多了一个p,但是用法却相当不一样. 在使用中,可以通过选择一个具有强语 ...
- javascript中数组的22种方法
前面的话数组总共有22种方法,本文将其分为对象继承方法.数组转换方法.栈和队列方法.数组排序方法.数组拼接方法.创建子数组方法.数组删改方法.数组位置方法.数组归并方法和数组迭代方法共10类来进行详细 ...
最新文章
- MonoScene: 单目3D语义场景补全
- numpy list df tensor的相互转换
- linux下gcc编译conio.h问题
- python中datetime模块_python中的datetime模块
- python合并ts视频_python爬取视频网站m3u8视频,下载.ts后缀文件,合并成整视频
- 将给定数据源生成静态HTML页面持久化到项目之外的硬盘
- Cocos Creator Ui系统
- python爬虫爬图片教程_python爬虫实战之爬取京东商城实例教程
- 25.conda 下载安装与运用
- Confluence 6 让一个空间可以公众访问
- 本学期课程教学要解决问题要点备忘录
- 【爬虫】花瓣图片爬虫,Python图片采集下载源码
- windows中nginx.exe注册为系统服务
- mysql 修改结束符_在MySQL中,用于设置MySQL结束符的关键字是【】
- OPA策略引擎用法实战
- Hair卡通渲染的效果(各向异性)
- 北美CS求学找工指南
- 在IntelliJ IDEA中使用Spring Initializr创建项目以及Maven集成与配置
- 数据库操作报错:字符串 ‘xxx:‘ 后的引号不完整
- 【Proteus仿真】6位数码管计时器(0-10^5)