我有两个 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中合并两个数组,以便获取每个数组中唯一的项,并以它们插入原始数组的相同顺序返回?
我知道这个问题与对象数组无关,但搜索者最终会到达这里。
因此,为了日后的读者,值得添加一个适当的ES6方法来合并然后删除重复项。
对象数组:
var arr1 = [ {a: 1}, {a: 2}, {a: 3} ];
var arr2 = [ {a: 1}, {a: 2}, {a: 4} ];
var arr3 = arr1.concat(arr2.filter( ({a}) => !arr1.find(f => f.a == a) ));
// [ {a: 1}, {a: 2}, {a: 3}, {a: 4} ]
避免嵌套循环(O(n^2)),以及 .indexOf()
(+O(n))。
function merge(a, b) {
var hash = {};
var i;
for (i = 0; i < a.length; i++) {
hash[a[i]] = true;
}
for (i = 0; i < b.length; i++) {
hash[b[i]] = true;
}
return Object.keys(hash);
}
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = merge(array1, array2);
console.log(array3);
只是提供我的意见。
function mergeStringArrays(a, b){
var hash = {};
var ret = [];
for(var i=0; i < a.length; i++){
var e = a[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
for(var i=0; i < b.length; i++){
var e = b[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
return ret;
}
这是我经常使用的一种方法,它使用一个对象作为哈希查找表来进行重复检查。假设哈希是O(1),那么它的时间复杂度为O(n),其中n为a.length + b.length。我并不知道浏览器如何进行哈希,但它在成千上万的数据点上表现良好。
String()
函数。虽然它对于原始值可能有效(尽管在类型之间存在冲突),但它不适用于对象数组。 - Bergi编辑:
当项目数量较少时,第一个解决方案是最快的。当有超过400个项目时,Set
解决方案变得最快。当有100,000个项目时,它比第一个解决方案快一千倍。
考虑到性能只在存在大量项目时才很重要,并且Set
解决方案远远比其他方案易读,所以在大多数情况下应该选择它作为正确的解决方案。
以下perf结果是使用少量项目计算的。
基于jsperf,在新数组中合并两个数组的最快方法(如果项目少于400个)如下:
for (var i = 0; i < array2.length; i++)
if (array1.indexOf(array2[i]) === -1)
array1.push(array2[i]);
这个慢了17%:
array2.forEach(v => array1.includes(v) ? null : array1.push(v));
这个比较慢,(注:在少于100个项目时。当有很多项目时,速度会快很多)速度慢了45%:
var a = [...new Set([...array1 ,...array2])];
被接受的答案比其他方法慢了55%(而且编写时间更长)(编辑:当有100,000个项目时,它比任何其他方法都慢几个数量级)
var a = array1.concat(array2);
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);
}
}
Set
更快,特别是在记录增加时(至少对于Numbers
而言)。请参见可运行的测试者:https://dev59.com/BHI-5IYBdhLWcg3w-9wK#66129415。 - OXiGENSet
已经改进了,或者它取决于数据的类型。我应该在我的答案中写下我的数组初始化:( - PitouliArray.prototype.merge = function(/* variable number of arrays */){
for(var i = 0; i < arguments.length; i++){
var array = arguments[i];
for(var j = 0; j < array.length; j++){
if(this.indexOf(array[j]) === -1) {
this.push(array[j]);
}
}
}
return this;
};
一个更好的数组合并函数。
var test = ['a', 'b', 'c']; console.log(test);
将打印出["a", "b", "c", merge: function]
- Doubidou今天2020年10月15日,我在MacOs HighSierra 10.13.6上使用Chrome v86、Safari v13.1.2和Firefox v81进行了选择解决方案的测试。
对于所有浏览器
我执行了2个测试用例:
对于A、 B、 C、 D、 E、 G、 H、 J、 L、 M, 在下面的代码片段中呈现。
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#10499519
function A(arr1,arr2) {
return _.union(arr1,arr2)
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#53149853
function B(arr1,arr2) {
return _.unionWith(arr1, arr2, _.isEqual);
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#27664971
function C(arr1,arr2) {
return [...new Set([...arr1,...arr2])]
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#48130841
function D(arr1,arr2) {
return Array.from(new Set(arr1.concat(arr2)))
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#23080662
function E(arr1,arr2) {
return arr1.concat(arr2.filter((item) => arr1.indexOf(item) < 0))
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#28631880
function G(arr1,arr2) {
var hash = {};
var i;
for (i = 0; i < arr1.length; i++) {
hash[arr1[i]] = true;
}
for (i = 0; i < arr2.length; i++) {
hash[arr2[i]] = true;
}
return Object.keys(hash);
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#13847481
function H(a, b){
var hash = {};
var ret = [];
for(var i=0; i < a.length; i++){
var e = a[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
for(var i=0; i < b.length; i++){
var e = b[i];
if (!hash[e]){
hash[e] = true;
ret.push(e);
}
}
return ret;
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#1584377
function J(arr1,arr2) {
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;
}
return arrayUnique(arr1.concat(arr2));
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#25120770
function L(array1, array2) {
const array3 = array1.slice(0);
let len1 = array1.length;
let len2 = array2.length;
const assoc = {};
while (len1--) {
assoc[array1[len1]] = null;
}
while (len2--) {
let itm = array2[len2];
if (assoc[itm] === undefined) { // Eliminate the indexOf call
array3.push(itm);
assoc[itm] = null;
}
}
return array3;
}
// https://dev59.com/BHI-5IYBdhLWcg3w-9wK#39336712
function M(arr1,arr2) {
const comp = f => g => x => f(g(x));
const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const afrom = apply(Array.from);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));
const dedupe = comp(afrom) (createSet);
const union = xs => ys => {
const zs = createSet(xs);
return concat(xs) (
filter(x => zs.has(x)
? false
: zs.add(x)
) (ys));
}
return union(dedupe(arr1)) (arr2)
}
// -------------
// TEST
// -------------
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
[A,B,C,D,E,G,H,J,L,M].forEach(f=> {
console.log(`${f.name} [${f([...array1],[...array2])}]`);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>
This snippet only presents functions used in performance tests - it not perform tests itself!
以下是Chrome浏览器的测试运行示例:
更新:
我删除了F、I、K三个案例,因为它们会修改输入数组,导致基准测试结果不正确。
为什么不使用对象呢?看起来你试图建模一个集合。但这种方法不会保留顺序。
var set1 = {"Vijendra":true, "Singh":true}
var set2 = {"Singh":true, "Shakya":true}
// Merge second object into first
function merge(set1, set2){
for (var key in set2){
if (set2.hasOwnProperty(key))
set1[key] = set2[key]
}
return set1
}
merge(set1, set2)
// Create set from array
function setify(array){
var result = {}
for (var item in array){
if (array.hasOwnProperty(item))
result[array[item]] = true
}
return result
}
if (!set1.hasOwnProperty(key))
? - GumboObject.keys()
数组中获取键的并集。 - OXiGEN对于ES6,只需一行代码:
a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))] // [1, 2, 3, 4, 5]
最佳解决方案...
您可以通过在浏览器控制台中输入以下命令直接检查...
a = [1, 2, 3];
b = [3, 2, 1, "prince"];
a.concat(b.filter(function(el) {
return a.indexOf(el) === -1;
}));
["prince", "asish", 5].concat(["ravi", 4])
如果你想要去重,可以尝试从这里找到更好的解决方案 - Shouting Code。
[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {
return [1, 2, 3].indexOf(el) === -1;
}));
在Chrome浏览器控制台中尝试
f12 > console
输出:
["prince", "asish", 5, "ravi", 4]
[1, 2, 3, "prince"]
我的一分半钱:
Array.prototype.concat_n_dedupe = function(other_array) {
return this
.concat(other_array) // add second
.reduce(function(uniques, item) { // dedupe all
if (uniques.indexOf(item) == -1) {
uniques.push(item);
}
return uniques;
}, []);
};
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var result = array1.concat_n_dedupe(array2);
console.log(result);
b
到a
) :a=a.concat(b);
从数组a
中删除重复项 (就地操作) :a=a.filter((i,p)=>a.indexOf(i)===p);
- ashleedawg