我有两个 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中合并两个数组,以便获取每个数组中唯一的项,并以它们插入原始数组的相同顺序返回?
最简单的方法是使用concat()
函数合并数组,然后使用filter()
函数来删除重复项;或者使用concat()
函数将合并后的数组放入一个Set()
中。
第一种方法:
const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
//now use filter to remove dups
const removeDuplicates = mergedArray.filter((elem, index) => mergedArray.indexOf(elem) === index); // [1,2,3, 4]
const firstArray = [1,2, 2];
const secondArray = [3,4];
// now lets merge them
const mergedArray = firstArray.concat(secondArray); // [1,2,2,3,4]
const removeDuplicates = new Set(mergedArray);
减少它们!!!
这种替代方案不是显式地合并和去重,而是使用另一个数组来缩小一个数组,使第一个数组的每个值都可以被累积迭代和解构,通过利用递归的数组持久性来忽略已经包含的值。
array2.reduce(reducer, array1.reduce(reducer, []))
测试示例:
var array1 = ["Vijendra","Singh","Singh"];
var array2 = ["Singh", "Shakya", "Shakya"];
const reducer = (accumulator, currentValue) => accumulator.includes(currentValue) ? accumulator : [...accumulator, currentValue];
console.log(
array2.reduce(reducer, array1.reduce(reducer, []))
);
// a reduce on first array is needed to ensure a deduplicated array used as initial value on the second array being reduced
结论
当需要避免枯燥的for-each方法时,这种方法更加优雅和有用(并不是说它没有用处)。
处理concat()在去重方面的限制。
无需使用Underscore.js、JQuery或Lo-Dash等外部库,也不需要麻烦地创建任何内置函数来实现所需的合并和去重效果。
哦,还有!它可以作为一行代码完成!
这个答案得益于ES5(ECMAScript 2015)美丽的include()和华丽的reduce()。
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
函数将两个数组合并。Array.prototype.union = function (other_array) {
/* you can include a test to check whether other_array really is an array */
other_array.forEach(function(v) { if(this.indexOf(v) === -1) {this.push(v);}}, this);
}
let array1 = ["Vijendra","Singh"];
let array2 = ["Singh", "Shakya"];
// Merges both arrays
let array3 = array1.concat(array2);
//REMOVE DUPLICATE
let removeDuplicate = [...new Set(array3)];
console.log(removeDuplicate);
import {pipe, concat, distinct} from 'iter-ops';
// our inputs:
const array1 = ['Vijendra', 'Singh'];
const array2 = ['Singh', 'Shakya'];
const i = pipe(
array1,
concat(array2), // adding array
distinct() // making it unique
);
console.log([...i]); //=> ['Vijendra', 'Singh', 'Shakya']
这是一段高性能代码,因为我们只迭代了一次,而且代码非常易读。
P.S. 我是iter-ops的作者。
另一种使用reduce函数的方法供您审查:
function mergeDistinct(arResult, candidate){
if (-1 == arResult.indexOf(candidate)) {
arResult.push(candidate);
}
return arResult;
}
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var arMerge = [];
arMerge = array1.reduce(mergeDistinct, arMerge);
arMerge = array2.reduce(mergeDistinct, arMerge);//["Vijendra","Singh","Shakya"];
制作了一个测试器,用于检查一些性能导向答案的速度。欢迎添加更多内容。到目前为止,Set
是最简单和最快的选项(随着记录数量增加,差距越大),至少对于简单的 Number
类型。
const records = 10000, //max records per array
max_int = 100, //max integer value per array
dup_rate = .5; //rate of duplication
let perf = {}, //performance logger,
ts = 0,
te = 0,
array1 = [], //init arrays
array2 = [],
array1b = [],
array2b = [],
a = [];
//populate randomized arrays
for (let i = 0; i < records; i++) {
let r = Math.random(),
n = r * max_int;
if (Math.random() < .5) {
array1.push(n);
r < dup_rate && array2.push(n);
} else {
array2.push(n);
r < dup_rate && array1.push(n);
}
}
//simple deep copies short of rfdc, in case someone wants to test with more complex data types
array1b = JSON.parse(JSON.stringify(array1));
array2b = JSON.parse(JSON.stringify(array2));
console.log('Records in Array 1:', array1.length, array1b.length);
console.log('Records in Array 2:', array2.length, array2b.length);
//test method 1 (jsperf per @Pitouli)
ts = performance.now();
for (let i = 0; i < array2.length; i++)
if (array1.indexOf(array2[i]) === -1)
array1.push(array2[i]); //modifies array1
te = performance.now();
perf.m1 = te - ts;
console.log('Method 1 merged', array1.length, 'records in:', perf.m1);
array1 = JSON.parse(JSON.stringify(array1b)); //reset array1
//test method 2 (classic forEach)
ts = performance.now();
array2.forEach(v => array1.includes(v) ? null : array1.push(v)); //modifies array1
te = performance.now();
perf.m2 = te - ts;
console.log('Method 2 merged', array1.length, 'records in:', perf.m2);
//test method 3 (Simplest native option)
ts = performance.now();
a = [...new Set([...array1, ...array2])]; //does not modify source arrays
te = performance.now();
perf.m3 = te - ts;
console.log('Method 3 merged', a.length, 'records in:', perf.m3);
//test method 4 (Selected Answer)
ts = performance.now();
a = array1.concat(array2); //does not modify source arrays
for (let i = 0; i < a.length; ++i) {
for (let j = i + 1; j < a.length; ++j) {
if (a[i] === a[j])
a.splice(j--, 1);
}
}
te = performance.now();
perf.m4 = te - ts;
console.log('Method 4 merged', a.length, 'records in:', perf.m4);
//test method 5 (@Kamil Kielczewski)
ts = performance.now();
function K(arr1, arr2) {
let r = [],
h = {};
while (arr1.length) {
let e = arr1.shift(); //modifies array1
if (!h[e]) h[e] = 1 && r.push(e);
}
while (arr2.length) {
let e = arr2.shift(); //modifies array2
if (!h[e]) h[e] = 1 && r.push(e);
}
return r;
}
a = K(array1, array2);
te = performance.now();
perf.m5 = te - ts;
console.log('Method 5 merged', a.length, 'records in:', perf.m4);
array1 = JSON.parse(JSON.stringify(array1b)); //reset array1
array2 = JSON.parse(JSON.stringify(array2b)); //reset array2
for (let i = 1; i < 6; i++) {
console.log('Method:', i, 'speed is', (perf['m' + i] / perf.m1 * 100).toFixed(2), '% of Method 1');
}
var MergeArrays=function(arrayOne, arrayTwo, equalityField) {
var mergeDictionary = {};
for (var i = 0; i < arrayOne.length; i++) {
mergeDictionary[arrayOne[i][equalityField]] = arrayOne[i];
}
for (var i = 0; i < arrayTwo.length; i++) {
mergeDictionary[arrayTwo[i][equalityField]] = arrayTwo[i];
}
return $.map(mergeDictionary, function (value, key) { return value });
}
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网站上的其他函数相比,性能有了显著的改善。
b
到a
) :a=a.concat(b);
从数组a
中删除重复项 (就地操作) :a=a.filter((i,p)=>a.indexOf(i)===p);
- ashleedawg