我有两个JavaScript数组:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
我希望输出为:
var array3 = ["Vijendra","Singh","Shakya"];
输出数组应删除重复的单词。
如何在JavaScript中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
我有两个JavaScript数组:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
我希望输出为:
var array3 = ["Vijendra","Singh","Shakya"];
输出数组应删除重复的单词。
如何在JavaScript中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
当前回答
下面是一个简单的例子:
var unique = function(array) {
var unique = []
for (var i = 0; i < array.length; i += 1) {
if (unique.indexOf(array[i]) == -1) {
unique.push(array[i])
}
}
return unique
}
var uniqueList = unique(["AAPL", "MSFT"].concat(["MSFT", "BBEP", "GE"]));
我们定义unique(array)来删除冗余元素,并使用concat函数来组合两个数组。
其他回答
ES2015的功能方法
按照函数方法,两个数组的联合只是concat和filter的组合。为了提供最佳性能,我们使用本机Set数据类型,该类型针对属性查找进行了优化。
无论如何,结合联合函数的关键问题是如何处理重复项。以下排列是可能的:
Array A + Array B
[unique] + [unique]
[duplicated] + [unique]
[unique] + [duplicated]
[duplicated] + [duplicated]
前两种排列很容易用一个函数处理。然而,后两个更复杂,因为只要依赖Set查找,就无法处理它们。由于切换到普通的旧Object属性查找会严重影响性能,因此下面的实现只会忽略第三个和第四个排列。你必须构建一个单独的union版本来支持它们。
//小型、可重复使用的辅助功能常量comp=f=>g=>x=>f(g(x));常量应用=f=>a=>f(a);常量flip=f=>b=>a=>f(a)(b);常量concat=xs=>y=>xs.contat(y);const afrom=应用(Array.from);const createSet=xs=>新集合(xs);常量过滤器=f=>xs=>xs.filter(apply(f));//重复数据消除常量重复数据删除=comp(afrom)(createSet);//实际联合函数常量并集=xs=>ys=>{const zs=创建集(xs);返回凹面(xs)(滤波器(x=>zs.has(x)? 假的:zs.add(x))(ys));}//模拟数据常量xs=[1,2,2,3,4,5];常量=[0,1,2,3,3,4,5,6,6];//我们来了console.log(“unique/unique”,union(重复数据消除(xs))(ys));console.log(“重复/唯一”,union(xs)(ys));
从这里开始,实现unionn函数变得很简单,它接受任意数量的数组(灵感来自naomik的评论):
//小型、可重复使用的辅助功能常量未修正=f=>(a,b)=>f(a)(b);常量foldl=f=>acc=>xs=>xs.reduce(uncurry(f),acc);常量应用=f=>a=>f(a);常量flip=f=>b=>a=>f(a)(b);常量concat=xs=>y=>xs.contat(y);const createSet=xs=>新集合(xs);常量过滤器=f=>xs=>xs.filter(apply(f));//工会和工会常量并集=xs=>ys=>{const zs=创建集(xs);返回凹面(xs)(滤波器(x=>zs.has(x)? 假的:zs.add(x))(ys));}常量unionn=(头,…尾)=>foldl(联合)(头)(尾);//模拟数据常量xs=[1,2,2,3,4,5];常量=[0,1,2,3,3,4,5,6,6];常数zs=[0,1,2,3,4,5,6,7,8,9];//我们来了console.log(unionn(xs,ys,zs));
事实证明unionn只是foldl(又名Array.protocol.reduce),它将union作为其缩减器。注意:由于实现没有使用额外的累加器,所以当您在没有参数的情况下应用它时,它会抛出错误。
仅合并阵列(不删除重复项)
ES5版本使用Array.concat:
var array1=[“Vijendra”,“Singh”];var array2=[“Singh”,“Shakya”];array1=array1.concat(array2);console.log(array1);
ES6版本使用销毁
const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];
由于没有“内置”的方法来删除重复项(ECMA-262实际上有Array.forEach,这将非常好),因此我们必须手动执行:
Array.prototype.unique = function() {
var a = this.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
};
然后,要使用它:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique();
这也将保持阵列的顺序(即,不需要排序)。
由于许多人对Array.prototype的原型扩充和in循环感到恼火,这里有一种不太侵入性的方法来使用它:
function arrayUnique(array) {
var a = array.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = arrayUnique(array1.concat(array2));
对于那些有幸使用ES5可用的浏览器的人,可以像这样使用Object.defineProperty:
Object.defineProperty(Array.prototype, 'unique', {
enumerable: false,
configurable: false,
writable: false,
value: function() {
var a = this.concat();
for(var i=0; i<a.length; ++i) {
for(var j=i+1; j<a.length; ++j) {
if(a[i] === a[j])
a.splice(j--, 1);
}
}
return a;
}
});
最好也是最简单的方法是使用JavaScript的函数“some()”,该函数返回true或false,指示数组是否包含对象的元素。您可以这样做:
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1;
array2.forEach(function(elementArray2){
var isEquals = array1.some(function(elementArray1){
return elementArray1 === elementArray2;
})
if(!isEquals){
array3.push(elementArray2);
}
});
console.log(array3);
结果:
["Vijendra", "Singh", "Shakya"]
如你所愿。。。无需复制。。。
我简化了这个答案的最佳部分,并将其转化为一个很好的函数:
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}
这是我的第二个答案,但我相信最快的答案是什么?我希望有人帮我检查并在评论中回复。
我的第一次尝试达到了99k操作/秒,这一次的复测是390k操作/每秒,而另一次领先的jsperf测试是140k(对我来说)。
http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26
这次我尝试尽可能减少阵列交互,看起来我获得了一些性能。
function findMerge(a1, a2) {
var len1 = a1.length;
for (var x = 0; x < a2.length; x++) {
var found = false;
for (var y = 0; y < len1; y++) {
if (a2[x] === a1[y]) {
found = true;
break;
}
}
if(!found){
a1.push(a2.splice(x--, 1)[0]);
}
}
return a1;
}
编辑:我对我的功能做了一些更改,与jsperf站点上的其他功能相比,性能非常出色。