我有两个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中合并两个数组,以便从每个数组中只获得唯一的项目,其顺序与它们插入原始数组的顺序相同?
当前回答
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作为其缩减器。注意:由于实现没有使用额外的累加器,所以当您在没有参数的情况下应用它时,它会抛出错误。
其他回答
使用Undercore.js或Lo Dash,您可以执行以下操作:
console.log(_.union([1,2,3],[101,2,1,10],[2,1]));<script src=“https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js“></script>
http://underscorejs.org/#union
http://lodash.com/docs#union
给定两个没有重复的简单类型的排序数组,这将在O(n)时间内合并它们,并且输出也将被排序。
function merge(a, b) {
let i=0;
let j=0;
let c = [];
for (;;) {
if (i == a.length) {
if (j == b.length) return c;
c.push(b[j++]);
} else if (j == b.length || a[i] < b[j]) {
c.push(a[i++]);
} else {
if (a[i] == b[j]) ++i; // skip duplicates
c.push(b[j++]);
}
}
}
下面是使用Set的另一个简单解决方案:
常量o1={a:1};const arr1=['!@#$%^&*()','gh',123,o1,1,true,undefined,null];常量arr2=['!@#$%^&*()',123,'abc',o1,0x001,true,void 0,0];const mergeUnique=(…args)=>[…新集合([].contat(…arg))];console.log(mergeUnique(arr1,arr2));
如果您合并对象数组,请考虑使用lodash UnionBy函数,它允许您设置自定义谓词比较对象:
import { unionBy } from 'lodash';
const a = [{a: 1, b: 2}];
const b = [{a: 1, b: 3}];
const c = [{a: 2, b: 4}];
const result = UnionBy(a,b,c, x => x.a);
结果是:〔{a:1;b:2},{a:2;b:4}〕
结果中使用了来自数组的第一个传递匹配
我简化了这个答案的最佳部分,并将其转化为一个很好的函数:
function mergeUnique(arr1, arr2){
return arr1.concat(arr2.filter(function (item) {
return arr1.indexOf(item) === -1;
}));
}