How to merge two arrays in JavaScript and de-duplicate items
Asked Answered
T

91

1983

I have two JavaScript arrays:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

I want the output to be:

var array3 = ["Vijendra","Singh","Shakya"];

The output array should have repeated words removed.

How do I merge two arrays in JavaScript so that I get only the unique items from each array in the same order they were inserted into the original arrays?

Taggart answered 18/10, 2009 at 8:34 Comment(2)
Before you post a new answer, consider there are already 75+ answers for this question. Please, make sure that your answer contributes information that is not among existing answers.Whiteman
If you want a more generic solution that also covers deep-merging, take a look at this question, instead. Some answers cover arrays as well.Eclosion
A
2304

To just merge the arrays (without removing duplicates)

ES5 version use Array.concat:

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];

array1 = array1.concat(array2);

console.log(array1);

2023 update

The original answer was from years ago. ES6 is fully supported and IE is finally dead. Here's the simplest way to merge primitive and object arrays:

const merge = (a, b, predicate = (a, b) => a === b) => {
    const c = [...a]; // copy to avoid side effects
    // add all items from B to copy C if they're not already present
    b.forEach((bItem) => (c.some((cItem) => predicate(bItem, cItem)) ? null : c.push(bItem)))
    return c;
}

merge(['a', 'b', 'c'], ['c', 'x', 'd']);
// => ['a', 'b', 'c', 'x', 'd']

merge([{id: 1}, {id: 2}], [{id: 2}, {id: 3}], (a, b) => a.id === b.id);
// [{id: 1}, {id: 2}, {id: 3}]

Original answer

ES6 version use destructuring

const array1 = ["Vijendra","Singh"];
const array2 = ["Singh", "Shakya"];
const array3 = [...array1, ...array2];

Since there is no 'built in' way to remove duplicates (ECMA-262 actually has Array.forEach which would be great for this), we have to do it manually. Note that this pollutes the Array prototype, use with caution.

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;
};

Then, to use it:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
// Merges both arrays and gets unique items
var array3 = array1.concat(array2).unique(); 

This will also preserve the order of the arrays (i.e, no sorting needed).

Since many people are annoyed about prototype augmentation of Array.prototype and for in loops, here is a less invasive way to use it:

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));

For those who are fortunate enough to work with browsers where ES5 is available, you can use Object.defineProperty like this:

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;
    }
});
Altorelievo answered 18/10, 2009 at 8:42 Comment(22)
Note that this algorithm is O(n^2).Madriene
Let [a, b, c] and [x, b, d] be the arrays (assume quotes). concat gives [a, b, c, x, b, d]. Wouldn't the unique()'s output be [a, c, x, b, d]. That doesn't preserve the order I think - I believe OP wants [a, b, c, x, d]Geology
But I think it's worth it. I learned that w3schools is not the best reference out there, that indexOf is in fact present in js and how to add it for older browsers, and a new use for the in keyword (from in this part in the MDC version of indexOf, I didn't know that).Geology
I originally up-voted this but have changed my mind. Assigning prototypes to Array.prototype has the consequences of breaking "for ... in" statements. So the best solution is probably to use a function like this but not assign it as a prototype. Some people may argue that "for ... in" statements shouldn't be used to iterate array elements anyway, but people often use them that way so at the very least this solution be used with caution.Shulman
@CodeCommander "but people often use them that way" - novice or bad programmers use it that way, that's why you have conventions. I used for in in arrays before, but I'd never do that again. Even some frameworks augment prototypes, so you shouldn't really care for breaking for in in arrays (and especially, you should never use it yourself!).Kerk
you should always use for ... in with hasOwnProperty in which case the prototype method is fineSwastika
just to note that the arrayUnique function doesn't really work for arrays which has more than two identical values ...Islamism
Does this work with classes in the array? e.g. questions: [Class, Class] after concat gives me []Endamage
You can do the "unique" bit in O(n) using something like var b=[]; for (var i=0,n=a.length;i<a;i++) { if (typeof(b[a[i]]) === 'undefined') { b[a[i]] = true; continue; } a.splice(i--, 1); }.Gantz
@DiegoNunes: your solution is still O(n^2) because removing an item from the array is O(n). Besides, table lookup is probably O(log n) so even fixing that won't make it linear.Groundsill
Just use Babel and Set() as described in another answer.Acetophenetidin
@Altorelievo I would replace the O(n^2) solution for the duplicate removal with the filter function. It should accept two parameters: the element and the index.Berner
Stelios -- that is still O(n^2) -- you are just hiding the outer loop in a system function. You need to go merge or hash or binary searchNotice
For other methods to dedup an array, please see my benchmarks at: jsperf.com/de-duplicate-an-array-keeping-only-unique-valuesEntitle
@AmrAli, your link is 404. jsperf.com/merge-two-arrays-keeping-only-unique-values by slickplaid works and shows this is the worst performing answer.Grubman
O(n^2) can be faster if the arrays are small because creating a Set object has some constant factor overhead due to allocation and GC. But this answer makes no mention that the algorithm is not scalable beyond small arrays. Even if you do need an O(n^2) algorithm, using filter and indexOf is more idiomatic and clean. The likely reason this answer is so highly upvoted is because it came on the stage first and got accepted back in 2009, but in nearly every respect it's a poor solution.Newsmonger
Just to add on top of original answer using ES6 filter/include, ignoring all big o comments: const array3 = [...array1, ...(array2.filter(v => !array1.includes(v)))];Heeltap
I don't like for. So I will prefer: simo's answer.Epizootic
Please understand that this answer was written over 11 years ago, when things like forEach and other nice things we're used to today did not exist.Altorelievo
Any danger in using the es6 version this way? templistarray = [...new Set([...list,...templistarray])];Heisler
It doesn't remove duplicatesEstrogen
lodash _.uniq makes the trick of uniquenessDaisie
C
663

With Underscore.js or Lo-Dash you can do:

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

Cobbs answered 8/5, 2012 at 13:24 Comment(8)
a set would by definition not preserve the order of a merged array because it does not have any order?Cloudburst
Or, perhaps even better than underscore, the API-compatible lodash.Stringent
@Cloudburst From the lodash docs. "Returns a new array of unique values, in order, that are present in one or more of the arrays."Kimberliekimberlin
Quick performance take on lodash vs the top answer: jsperf.com/merge-two-arrays-keeping-only-unique-valuesChilton
@weaver if you want to pass an array you could just use .apply()Vaginectomy
Uncaught ReferenceError: _ is not defined I don't want to use any libraries, there is other, easiest way, for example: array.concact(otherArrays); - this is also one line and lot faster.Fast
@TimoHuovinen I added [...new Set(array1.concat(array2))] to slickplaid's jsperf and it is the same speed as lodash which is slow compared to alternatives. Still better than the top answer. (I've never needed to down vote a top answer before.)Grubman
Archive of the performance tests: web.archive.org/web/20200803234803/http://jsperf.com/…Dilution
R
449
[...array1,...array2] //   =>  don't remove duplication 

OR

[...new Set([...array1 ,...array2])]; //   => remove duplication
Rite answered 14/8, 2016 at 8:8 Comment(9)
1st/2nd example is no union at all + 1st example blows up the stack for large Arrays + 3rd example is incredibly slow and consumes a lot of memory, since two intermediate Arrays have to be build + 3rd example can only be used for union with a known number of Arrays at compile time.Grime
so how you would do it ?Joslyn
Note that for set can't deduplicate two objects that have the same key value pairs unless they are the same object references.Sheriff
should be accepted answer for the modern of Javascript.Lothair
Does not work with an array of objects, as it'll only merge object references and doesn't care if the objects themselves are equal.Egwin
this is really the best answer, I tried to compare with array.find by id, array concact and wasnt fast like yours solution, best man thank youKermie
for merging different objects without duplicating : https://mcmap.net/q/45781/-javascript-merge-two-arrays-of-objects-only-if-not-duplicate-based-on-specified-object-keyScorpaenoid
array1.push(...array2) // => don't remove duplication it doest concatenate arrays but add new array as last element of array1Cup
This creates object instead of arrayFactorize
O
424

First concatenate the two arrays, next filter out only the unique items:

var a = [1, 2, 3], b = [101, 2, 1, 10]
var c = a.concat(b)
var d = c.filter((item, pos) => c.indexOf(item) === pos)

console.log(d) // d is [1, 2, 3, 101, 10]

Edit

As suggested a more performance wise solution would be to filter out the unique items in b before concatenating with a:

var a = [1, 2, 3], b = [101, 2, 1, 10]
var c = a.concat(b.filter((item) => a.indexOf(item) < 0))

console.log(c) // c is [1, 2, 3, 101, 10]
Overalls answered 15/4, 2014 at 10:8 Comment(8)
The original solution here has the benefit of removing dupes within each source array. I guess it depends on your context which you would use.Egotist
You could merge different for IE6-support: c = Array.from(new Set(c));Hellfire
If I want to actually change a to add b, will it then be better to loop through and use push? a.forEach(function(item){ if(a.indexOf(item)<0) a.push(item); });Cyna
Just a reminder of the current browser usage caniuse.com/usage-table for people anxious about IE6.Mintz
@Andrew: Even better: 1. var c = [...a, ...b.filter(o => !~a.indexOf(o))]; 2. var c = [...new Set([...a, ...b])];Streptokinase
@Streptokinase If more obscure and shorter is better then maybe?Immanent
@Immanent I suspect that the 2nd approach mentioned will become widely used since if it's understood what Sets are, it is actually pretty readable and not too "clever". The 1st method takes a bit of reading.Latchkey
Can we use it in associative array? let a = [{id: 1, name:"sam", id:2, name: "roy" }]; let b = [{id: 1, name:"sam", id:3, name: "john" }] Output should be [{id: 1, name:"sam", id:2, name: "roy" , id:3, name: "john"}]Mandie
C
285

This is an ECMAScript 6 solution using spread operator and array generics.

Currently it only works with Firefox, and possibly Internet Explorer Technical Preview.

But if you use Babel, you can have it now.

const input = [
  [1, 2, 3],
  [101, 2, 1, 10],
  [2, 1]
];
const mergeDedupe = (arr) => {
  return [...new Set([].concat(...arr))];
}

console.log('output', mergeDedupe(input));
Clifford answered 27/12, 2014 at 6:28 Comment(14)
This should be added to the accepted answer. This solution is much more efficient and much more elegant than what's currently possible but it's what we'll inevitably be able to do (and should do to keep up in this field).Threonine
This isn't quiiite the same as the OP's question (this seems to be more of a flatmap than anything) but upvote because it's awesome.Uchish
@jedd.ahyoung: make it mergeDedupe(...arr) and you can call it like mergeDedupe(array1, array2) which is exactly what the OP wants.Chatoyant
Um, the Array constructor has no static concat method? (Proprietary FF ignored). You should make that [].concat(...arr).Chatoyant
Babel only converts syntax. You need a transform for Set to fully work in IE10 and Safari, which can be messyPatience
Hard to say that this should be the accepted answer since the question is from 2009. But yes, this not only is more "performant" but also "elegant"Titanism
Array.from can be used instead of spread operator: Array.from(new Set([].concat(...arr)))Houghton
@Bergi: var mergeDeduplicate = (...arrayOfArrays) => [...new Set([].concat(...arrayOfArrays))];Streptokinase
@Streptokinase Is that a question?Chatoyant
@Bergi: No, an answer ☺. You said “make it”, so I made it... and improved even more.Streptokinase
The current accepted answer refers to ES6 without this elegant answer, it should be revised to include itParham
@HenryBlyth So what do you think ...arr is? What's the point in using Array.from instead of the spread operator if you're still using ...arr inside?Epanorthosis
This is very elegant. Unfortunately Typescript doesn't support this yet. #33465004Palatal
why not just return [...new Set(arr)]; rather than return [...new Set([].concat(...arr))];? Not saying it is wrong just wondering why you have to do thisNativeborn
R
147

Using a Set (ECMAScript 2015), it will be as simple as that:

const array1 = ["Vijendra", "Singh"];
const array2 = ["Singh", "Shakya"];
console.log(Array.from(new Set(array1.concat(array2))));
Rossen answered 6/1, 2018 at 19:5 Comment(4)
I Consider this the "Accepted Answer" for using ES6.Chiclayo
@Chiclayo How about: const array3 = [...new Set(array1.concat(array2))]Mcgill
It doesn't work if you are using an Array of objectsElledge
for merging different objects without duplicating : https://mcmap.net/q/45781/-javascript-merge-two-arrays-of-objects-only-if-not-duplicate-based-on-specified-object-keyScorpaenoid
M
47

You can do it simply with ECMAScript 6,

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [...new Set([...array1 ,...array2])];
console.log(array3); // ["Vijendra", "Singh", "Shakya"];
  • Use the spread operator for concatenating the array.
  • Use Set for creating a distinct set of elements.
  • Again use the spread operator to convert the Set into an array.
Mufi answered 7/4, 2016 at 7:26 Comment(3)
I get error: Type 'Set<string>' is not an array type.Emprise
And if you for some reason don't want to use the spread operator, there's also: Array.from(new Set(array1.concat(array2))).Pax
@gattsbr, with TypeScript in tsconfig.json, you can add "downlevelIteration": true to compilerOptions.Estrogen
C
43

Here is a slightly different take on the loop. With some of the optimizations in the latest version of Chrome, it is the fastest method for resolving the union of the two arrays (Chrome 38.0.2111).

JSPerf: "Merge two arrays keeping only unique values" (archived)

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = [];

var arr = array1.concat(array2),
  len = arr.length;

while (len--) {
  var itm = arr[len];
  if (array3.indexOf(itm) === -1) {
    array3.unshift(itm);
  }
}

while loop: ~589k ops/s
filter: ~445k ops/s
lodash: 308k ops/s
for loops: 225k ops/s

A comment pointed out that one of my setup variables was causing my loop to pull ahead of the rest because it didn't have to initialize an empty array to write to. I agree with that, so I've rewritten the test to even the playing field, and included an even faster option.

JSPerf: "Merge two arrays keeping only unique values" (archived)

let whileLoopAlt = function (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;
};

In this alternate solution, I've combined one answer's associative array solution to eliminate the .indexOf() call in the loop which was slowing things down a lot with a second loop, and included some of the other optimizations that other users have suggested in their answers as well.

The top answer here with the double loop on every value (i-1) is still significantly slower. lodash is still doing strong, and I still would recommend it to anyone who doesn't mind adding a library to their project. For those who don't want to, my while loop is still a good answer and the filter answer has a very strong showing here, beating out all on my tests with the latest Canary Chrome (44.0.2360) as of this writing.

Check out Mike's answer and Dan Stocker's answer if you want to step it up a notch in speed. Those are by far the fastest of all results after going through almost all of the viable answers.

Chilton answered 4/8, 2014 at 14:14 Comment(8)
There's a flaw in your methodology: you put the creation of array3 into the setup phase, while that cost should only be part of your while-based solution's score. With this 1 line moved, your solution falls to the speed of the for loop based one. I understand that array can be reused, but maybe the other algorithms could benefit too from not having to declare and initialize every necessary building block.Unvoiced
I agree with your premise @doldt, but disagree with your results. There is a fundamental design flaw with the loop based removal of entries, in that you have to recheck the length of the array after you have removed items, resulting in a slower execution time. A while loop working backwards does not have these effects. Here is an example with removing as many setup variables as I can without changing their original answer too much: jsperf.com/merge-two-arrays-keeping-only-unique-values/19Chilton
@Chilton the linked tests are empty, and the next revision at jsperf hangs in the while loop.Unvoiced
@Unvoiced I've addressed your concerns in my answer and added a proper updated test to it as well. Let me know if you agree with those results or not. Also, I added another better result using an associative array.Chilton
@slickpaid Thanks, good job on the extended perf page, very comprehensive!Unvoiced
@Chilton Thanks for setting up the extended perf page. Unless I'm missing something, the "whileLoopAlt2" function doesn't work? It creates a new array containing the first array, and the second array (in reverse order). To avoid confusion I've made another revision that removes the broken function. I also added an additional example: jsperf.com/merge-two-arrays-keeping-only-unique-values/22Hexane
whileLoopAlt function does not removes all duplicates.Loblolly
I took the liberty of updating the comprehensive jsperf page. I fixed whileLoopAlt2 by adding an initial population of the comparison hash, so now whileLoopAlt2 produces an array with only unique results; it's still pretty fast. Added new test differentiated by an undefined check rather than a falsy, for a faster whileLoopAlt3. And added an even faster(fastest) whileLoopAlt4 which uses null assignments rather than Booleans to save a tiny bit of speed.Ruthful
I
38

I simplified the best of this answer and turned it into a nice function:

function mergeUnique(arr1, arr2){
    return arr1.concat(arr2.filter(function (item) {
        return arr1.indexOf(item) === -1;
    }));
}
Immanent answered 9/6, 2017 at 17:56 Comment(5)
I believe this is much cleaner than the accepted answer. Also it looks like filter is supported in ECMAScript 5.1 + which is pretty supported now.Footing
this is so much more succinct.Owing
one liner: const mergeUnique = (a, b) => a.concat(b.filter(v => a.indexOf(v) === -1))Softshoe
This does not remove dups from arr1, it only adds unique elements from arr2Calley
One can use findIndex for finding index of objects by their property values within the filter() function like so: const index = arr1.findIndex(i => i.id === item.id);Howbeit
W
35

The ES6 offers a single-line solution for merging multiple arrays without duplicates by using destructuring and set.

const array1 = ['a','b','c'];
const array2 = ['c','c','d','e'];
const array3 = [...new Set([...array1,...array2])];
console.log(array3); // ["a", "b", "c", "d", "e"]
Whitmire answered 24/8, 2021 at 6:38 Comment(2)
This adds nothing to the identical answers already provided in 2016Inextirpable
And does not work for arrays of objectsSherrard
G
32

I know this question is not about array of objects, but searchers do end up here.

so it's worth adding for future readers a proper ES6 way of merging and then removing duplicates

array of objects:

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} ]
Gorizia answered 2/12, 2019 at 15:49 Comment(0)
O
29

Just steer clear of nested loops (O(n^2)), and .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);
Orphism answered 20/2, 2015 at 14:55 Comment(1)
That's pretty amazing, especially if you're doing strings. Numbers would need an additional step to keep them as such. This function heftily beats out all other options if you don't mind (or care) that everything is a string after you're finished. Nice job. Performance results here: jsperf.com/merge-two-arrays-keeping-only-unique-values/21Chilton
L
27

Just throwing in my two cents.

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;
}

This is a method I use a lot, it uses an object as a hashlookup table to do the duplicate checking. Assuming that the hash is O(1), then this runs in O(n) where n is a.length + b.length. I honestly have no idea how the browser does the hash, but it performs well on many thousands of data points.

Leith answered 12/12, 2012 at 19:50 Comment(3)
Very nicely done. Beats out quite (if not all) of the other results on this page by leveraging the associative array and keeping out the looping of indexOf and other operations. jsperf.com/merge-two-arrays-keeping-only-unique-values/21Chilton
Your "hash" is the String() function in javascript. Which might work for primitive values (albeit with collisions between types), but it's not a good fit for arrays of objects.Chatoyant
I use a similar solution, I allow passing a hashCode function or passing a string to identify a property in the object to use as the hash key.Dishonesty
I
23

EDIT:

The first solution is the fastest only when there are few items. When there are over 400 items, the Set solution becomes the fastest. And when there are 100,000 items, it is a thousand times faster than the first solution.

Considering that performance is important only when there is a lot of items, and that the Set solution is by far the most readable, it should be the right solution in most cases

The perf results below were computed with a small number of items


Based on jsperf, the fastest way (edit: if there are less than 400 items) to merge two arrays in a new one is the following:

for (var i = 0; i < array2.length; i++)
    if (array1.indexOf(array2[i]) === -1)
      array1.push(array2[i]);

This one is 17% slower:

array2.forEach(v => array1.includes(v) ? null : array1.push(v));

This one is 45% slower (edit: when there is less than 100 items. It is a lot faster when there is a lot of items):

var a = [...new Set([...array1 ,...array2])];

And the accepted answer's is 55% slower (and much longer to write) (edit: and it is several order of magnitude slower than any of the other methods when there are 100,000 items)

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);
    }
}

https://jsbench.me/lxlej18ydg

Interweave answered 26/2, 2020 at 20:12 Comment(3)
Thanks for this and putting the performance numbers in easy to understand ranked % figures. I was originally searching for Set based options because of simplicity. Given my datasets can get very large, performance is definitely a more important consideration!Canst
Turns out Set is much faster, especially as the records increase (for Numbers at least). See runnable testers at https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items.Canst
@Canst Yep, either the browser implementation of Set has been improved, or it depends of the type of data. I should have written my arrays initialization in my answer :(Interweave
O
20
Array.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;
};

A much better array merge function.

Obediah answered 19/8, 2011 at 13:34 Comment(6)
var test = ['a', 'b', 'c']; console.log(test); will print ["a", "b", "c", merge: function]Spodumene
Excellent solution. I've updated the jsperf test posted above by @Chilton (jsperf.com/merge-two-arrays-keeping-only-unique-values/3) and it looks like this is the fastest one of them.Randarandal
@Randarandal At the risk of sounding petty, running on Chrome 40.0.2214 (Latest as of 2/18/15), this answer is 53% slower than mine. OTOH IE11 seems not optimized for my answer at all. :) Chrome mobile is still rocking it, though. Honestly, if you're using lodash/_ which most of us should, the true answer is already pretty high up on this list. :)Chilton
@Chilton True, and it's quite a bit faster, even compared to the lodash/_ one. I'll probably end up switching my implementation at one point or another to something similar to yours. :DRandarandal
what is Array ? is it where your output is saved ? is it saved in Array ? I have one array that has multiple arrays inside it . Eg -> abc = [ ['a'], ['b'], ['c','d','e'] ] ...so will it be like Array.prototype.merge = function(abc) { //code }Mediaeval
Not sure what the costs of indexOf() method are but this is probably the fastest ES5 compatible method. Also worth nothing that the variable length of arguments is not needed. This method is chainable. @Chilton Loading a library is never an answer to a "how to do it in javascript" question. surely many libraries have a function to get this 7 lines job done.Donnelldonnelly
C
19

Performance

Today 2020.10.15 I perform tests on MacOs HighSierra 10.13.6 on Chrome v86, Safari v13.1.2 and Firefox v81 for chosen solutions.

Results

For all browsers

  • solution H is fast/fastest
  • solutions L is fast
  • solution D is fastest on chrome for big arrays
  • solution G is fast on small arrays
  • solution M is slowest for small arrays
  • solutions E are slowest for big arrays

enter image description here

Details

I perform 2 tests cases:

  • for 2 elements arrays - you can run it HERE
  • for 10000 elements arrays - you can run it HERE

on solutions A, B, C, D, E, G, H, J, L, M presented in below snippet

// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
function A(arr1,arr2) {
  return _.union(arr1,arr2)
}

// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
function B(arr1,arr2) {
  return _.unionWith(arr1, arr2, _.isEqual);
}

// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
function C(arr1,arr2) {
  return [...new Set([...arr1,...arr2])]
}

// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
function D(arr1,arr2) {
  return Array.from(new Set(arr1.concat(arr2)))
}

// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
function E(arr1,arr2) {
  return arr1.concat(arr2.filter((item) => arr1.indexOf(item) < 0))
}


// https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
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://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
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://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
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://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
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://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items
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!

And here are example test run for chrome

enter image description here

UPDATE

I remove cases F,I,K because they modify input arrays and benchmark gives wrong results

Chemotropism answered 15/10, 2020 at 11:21 Comment(5)
why don't you improve the first snippet and remove the code duplication?Introspection
@Introspection I don't know how to improve first snippet without loosing performance or simplicity - but I'm open to your solution - feel free to create new answer where you improve this solution in such way - everybody will be happy :)Rampage
@KamilKiełczewski : Careful! I have a strong suspicion that there is a bug in the test. When you add a console.log with the length of the arrays, you observe that the length is 0 in most cases. It feels like the array is not correctly reset between each run. And then of course, merging two null array is a very fast operation ;) This seems to be confirmed by this answer https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-items where the K solution is fast, but less than the C solution (careful ; only look at the % comparaison; there is an error in the snippet and the chrono is wrong)Interweave
I confirm my suspicion. I updated the test bench so the array is parsed from an unmodified json. Obviously, every test is a bit slower, but it does not impact the ranking. And the K test is significantly slower than the C, D, L & M tests (on Mac Chrome). jsbench.me/mpklq0sj6l/1Interweave
@Interweave you are right - I update answer and remove solutions which changes input arrays F,I,K - because benchmark gives wrong results for it (when I have more time in future I will try to benchmark dropped solutions again)Rampage
C
17

Why don't you use an object? It looks like you're trying to model a set. This won't preserve the order, however.

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
}
Cologarithm answered 18/10, 2009 at 8:51 Comment(3)
Don’t you mean if (!set1.hasOwnProperty(key))?Madriene
Why would I mean that? The purpose of that condition is to ignore properties that may be in the object's prototype.Cologarithm
It is not efficient to convert to objects in every use case. For example, we might want the union of keys from 2 arrays of Object.keys().Canst
R
14

For ES6, just one line:

a = [1, 2, 3, 4]
b = [4, 5]
[...new Set(a.concat(b))]  // [1, 2, 3, 4, 5]
Rhodonite answered 22/9, 2018 at 9:10 Comment(0)
U
12

The best solution...

You can check directly in the browser console by hitting...

Without duplicate

a = [1, 2, 3];
b = [3, 2, 1, "prince"];

a.concat(b.filter(function(el) {
    return a.indexOf(el) === -1;
}));

With duplicate

["prince", "asish", 5].concat(["ravi", 4])

If you want without duplicate you can try a better solution from here - Shouting Code.

[1, 2, 3].concat([3, 2, 1, "prince"].filter(function(el) {
    return [1, 2, 3].indexOf(el) === -1;
}));

Try on Chrome browser console

 f12 > console

Output:

["prince", "asish", 5, "ravi", 4]

[1, 2, 3, "prince"]
Unhinge answered 22/3, 2016 at 5:17 Comment(1)
It does not remove duplicates from the output array.Sanfordsanfourd
H
10

My one and a half penny:

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);
Hellhound answered 12/10, 2015 at 15:53 Comment(2)
It doesn't use anything that is new in ES6, did I miss something?Chatoyant
@Bergi: Yes, you are right. Thank you for noting. Somehow I was playing with this script and probably there was some version with ES6 function, but now it contains indexOf which is there for centuries. My mistake, sorry.Hellhound
B
10

There are so many solutions for merging two arrays. They can be divided into two main categories(except the use of 3rd party libraries like lodash or underscore.js).

a) combine two arrays and remove duplicated items.

b) filter out items before combining them.

Combine two arrays and remove duplicated items

Combining

// mutable operation(array1 is the combined array)
array1.push(...array2);
array1.unshift(...array2);

// immutable operation
const combined = array1.concat(array2);
const combined = [...array1, ...array2];    // ES6

Unifying

There are many ways to unifying an array, I personally suggest below two methods.

// a little bit tricky
const merged = combined.filter((item, index) => combined.indexOf(item) === index);
const merged = [...new Set(combined)];

Filter out items before combining them

There are also many ways, but I personally suggest the below code due to its simplicity.

const merged = array1.concat(array2.filter(secItem => !array1.includes(secItem)));
Blaineblainey answered 25/11, 2019 at 19:16 Comment(0)
C
10

you can use new Set to remove duplication

[...new Set([...array1 ,...array2])]
Creator answered 17/6, 2022 at 17:26 Comment(2)
Note that this retain the orderAlanalana
Great solution for arrays of strings but won't work on array of objects.Howbeit
B
9

You can achieve it simply using Underscore.js's => uniq:

array3 = _.uniq(array1.concat(array2))

console.log(array3)

It will print ["Vijendra", "Singh", "Shakya"].

Barbi answered 18/4, 2017 at 12:47 Comment(0)
C
8

New solution ( which uses Array.prototype.indexOf and Array.prototype.concat ):

Array.prototype.uniqueMerge = function( a ) {
    for ( var nonDuplicates = [], i = 0, l = a.length; i<l; ++i ) {
        if ( this.indexOf( a[i] ) === -1 ) {
            nonDuplicates.push( a[i] );
        }
    }
    return this.concat( nonDuplicates )
};

Usage:

>>> ['Vijendra', 'Singh'].uniqueMerge(['Singh', 'Shakya'])
["Vijendra", "Singh", "Shakya"]

Array.prototype.indexOf ( for internet explorer ):

Array.prototype.indexOf = Array.prototype.indexOf || function(elt)
  {
    var len = this.length >>> 0;

    var from = Number(arguments[1]) || 0;
    from = (from < 0) ? Math.ceil(from): Math.floor(from); 
    if (from < 0)from += len;

    for (; from < len; from++)
    {
      if (from in this && this[from] === elt)return from;
    }
    return -1;
  };
Counselor answered 18/10, 2009 at 8:42 Comment(13)
@Mender: if order is not matter then how I do thisTaggart
It's not a standard ECMAScript method defined for Array.prototype, though I'm aware you can easily define it for IE and other browsers which don't support it.Counselor
Note that this algorithm is O(n^2).Madriene
What algorithm is your answer?Counselor
@meder: My algorithm is a union algorithm. The union itself is done in O(n+m), but sorting takes at most O(n·log n+m·log m). So the whole algorithm is O(n·log n+m·log m).Madriene
@Altorelievo your solution doesn't seem to preserve the order. [a,b,c] and [x,b,d] would give [a,c,x,b,d] instead of [a,b,c,x,d].Geology
did you find out what does >>> 0 do in there? I can't think of an example where >>> 0 would make any difference.Geology
@Amarghosh: My solution wasn't posted after the OP's comment about order.Altorelievo
Can any of you downvoters actually explain why you downvoted? My original solution solved the OP's issue, and my updated code does the same. The selected answer did not initially account for the ordering to which it was fixed later.Counselor
It's unfair, this should definitely come on top of the jQuery one, at least.Geology
This is a good answer, although I am prompted to down-vote simply from the poor code that is shown here. That array.prototype.uniqueMerge function is horrendous, I haven't looked at the rest.Obediah
@meder First of all, why do you make an array of 'non-duplicates' and then concat them to the original array? why not just push the 'non-duplicates' to the original array to begin with. Secondly, why the **** do you have 'l = a.length; i < l' ?? it should be 'i < a.length'. Your causing ridiculous extra lines of execution, to the point where it is just pure wrong.Obediah
I should note before you try to tell me that 'l = a.length; i < l' is faster because it only does 'one calculation'; that this is not the case. Unlike some other languages, in javascript '.length' is a property on all arrays, not a calculation.Obediah
I
8

It can be done using Set.

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var array3 = array1.concat(array2);
var tempSet = new Set(array3);
array3 = Array.from(tempSet);

//show output
document.body.querySelector("div").innerHTML = JSON.stringify(array3);
<div style="width:100%;height:4rem;line-height:4rem;background-color:steelblue;color:#DDD;text-align:center;font-family:Calibri" > 
  temp text 
</div>
Immunoreaction answered 29/3, 2018 at 19:6 Comment(0)
G
7
//Array.indexOf was introduced in javascript 1.6 (ECMA-262) 
//We need to implement it explicitly for other browsers, 
if (!Array.prototype.indexOf)
{
  Array.prototype.indexOf = function(elt, from)
  {
    var len = this.length >>> 0;

    for (; from < len; from++)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
//now, on to the problem

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var merged = array1.concat(array2);
var t;
for(i = 0; i < merged.length; i++)
  if((t = merged.indexOf(i + 1, merged[i])) != -1)
  {
    merged.splice(t, 1);
    i--;//in case of multiple occurrences
  }

Implementation of indexOf method for other browsers is taken from MDC

Geology answered 18/10, 2009 at 8:43 Comment(5)
I couldn't find it in w3schools, that's why I wrote it. w3schools.com/jsref/jsref_obj_array.asp Does it take a from parameter btw?Geology
Thanks @Madriene and @meder - gonna change my bookmarks now. I'm yet to do anything serious in js and I use w3schools for casual reference (that's all I've ever needed) - may be that's why I didn't realize that.Geology
MDC says indexOf requires javascript 1.6 Would it be safe to assume that the common browsers (>= FF2, > IE6 etc) would support it?Geology
IE6 doesn't support Array.prototype.indexOf, just paste the support method given by Mozilla so IE doesn't throw an error.Counselor
updated using indexOf. Cleaned up the code by removing commented part. @meder - thanks again.Geology
A
7
const array3 = array1.filter(t=> !array2.includes(t)).concat(array2)
Awl answered 8/7, 2022 at 3:52 Comment(4)
Please read How do I write a good answer?. While this code block may answer the OP's question, this answer would be much more useful if you explain how this code is different from the code in the question, what you've changed, why you've changed it and why that solves the problem without introducing others.Ashbey
This question is nearly 13 years old and already has over 100 answers, including an accepted answer with a score of over 2,000. Are you entirely sure that this answer has not already been given? If so, please edit it to explain how it improves upon what is already here.Oilbird
it is the best answer, already has a likeAwl
Seems like a pretty good answer to me. I'm glad the world doesn't work like SO too many rules that I can't be arsed to learnAlanalana
D
6
Array.prototype.add = function(b){
    var a = this.concat();                // clone current object
    if(!b.push || !b.length) return a;    // if b is not an array, or empty, then return a unchanged
    if(!a.length) return b.concat();      // if original is empty, return b

    // go through all the elements of b
    for(var i = 0; i < b.length; i++){
        // if b's value is not in a, then add it
        if(a.indexOf(b[i]) == -1) a.push(b[i]);
    }
    return a;
}

// Example:
console.log([1,2,3].add([3, 4, 5])); // will output [1, 2, 3, 4, 5]
Different answered 26/7, 2013 at 11:38 Comment(0)
C
6
array1.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)

The nice thing about this one is performance and that you in general, when working with arrays, are chaining methods like filter, map, etc so you can add that line and it will concat and deduplicate array2 with array1 without needing a reference to the later one (when you are chaining methods you don't have), example:

someSource()
.reduce(...)
.filter(...)
.map(...) 
// and now you want to concat array2 and deduplicate:
.concat(array2).filter((value, pos, arr)=>arr.indexOf(value)===pos)
// and keep chaining stuff
.map(...)
.find(...)
// etc

(I don't like to pollute Array.prototype and that would be the only way of respect the chain - defining a new function will break it - so I think something like this is the only way of accomplish that)

Claireclairobscure answered 8/6, 2018 at 3:38 Comment(0)
K
5

DeDuplicate single or Merge and DeDuplicate multiple array inputs. Example below.

useing ES6 - Set, for of, destructuring

I wrote this simple function which takes multiple array arguments. Does pretty much the same as the solution above it just have more practical use case. This function doesn't concatenate duplicate values in to one array only so that it can delete them at some later stage.

SHORT FUNCTION DEFINITION ( only 9 lines )

/**
* This function merging only arrays unique values. It does not merges arrays in to array with duplicate values at any stage.
*
* @params ...args Function accept multiple array input (merges them to single array with no duplicates)
* it also can be used to filter duplicates in single array
*/
function arrayDeDuplicate(...args){
   let set = new Set(); // init Set object (available as of ES6)
   for(let arr of args){ // for of loops through values
      arr.map((value) => { // map adds each value to Set object
         set.add(value); // set.add method adds only unique values
      });
   }
   return [...set]; // destructuring set object back to array object
   // alternativly we culd use:  return Array.from(set);
}

USE EXAMPLE CODEPEN:

// SCENARIO 
let a = [1,2,3,4,5,6];
let b = [4,5,6,7,8,9,10,10,10];
let c = [43,23,1,2,3];
let d = ['a','b','c','d'];
let e = ['b','c','d','e'];

// USEAGE
let uniqueArrayAll = arrayDeDuplicate(a, b, c, d, e);
let uniqueArraySingle = arrayDeDuplicate(b);

// OUTPUT
console.log(uniqueArrayAll); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 43, 23, "a", "b", "c", "d", "e"]
console.log(uniqueArraySingle); // [4, 5, 6, 7, 8, 9, 10]
Knickerbockers answered 5/6, 2018 at 2:46 Comment(2)
Why use arr.map here? You're using it as a foreach, as the result is ignoredPlatinocyanide
I used return Array.from(set.values()); , because vscode gives error for return [...set];Adaptive
G
4

A functional approach with ES2015

Following the functional approach a union of two Arrays is just the composition of concat and filter. In order to provide optimal performance we resort to the native Set data type, which is optimized for property lookups.

Anyway, the key question in conjunction with a union function is how to treat duplicates. The following permutations are possible:

Array A      + Array B

[unique]     + [unique]
[duplicated] + [unique]
[unique]     + [duplicated]
[duplicated] + [duplicated]

The first two permutations are easy to handle with a single function. However, the last two are more complicated, since you can't process them as long as you rely on Set lookups. Since switching to plain old Object property lookups would entail a serious performance hit the following implementation just ignores the third and fourth permutation. You would have to build a separate version of union to support them.


// small, reusable auxiliary functions

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));


// de-duplication

const dedupe = comp(afrom) (createSet);


// the actual union function

const union = xs => ys => {
  const zs = createSet(xs);  
  return concat(xs) (
    filter(x => zs.has(x)
     ? false
     : zs.add(x)
  ) (ys));
}


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];


// here we go

console.log( "unique/unique", union(dedupe(xs)) (ys) );
console.log( "duplicated/unique", union(xs) (ys) );

From here on it gets trivial to implement an unionn function, which accepts any number of arrays (inspired by naomik's comments):

// small, reusable auxiliary functions

const uncurry = f => (a, b) => f(a) (b);
const foldl = f => acc => xs => xs.reduce(uncurry(f), acc);

const apply = f => a => f(a);
const flip = f => b => a => f(a) (b);
const concat = xs => y => xs.concat(y);
const createSet = xs => new Set(xs);
const filter = f => xs => xs.filter(apply(f));


// union and unionn

const union = xs => ys => {
  const zs = createSet(xs);  
  return concat(xs) (
    filter(x => zs.has(x)
     ? false
     : zs.add(x)
  ) (ys));
}

const unionn = (head, ...tail) => foldl(union) (head) (tail);


// mock data

const xs = [1,2,2,3,4,5];
const ys = [0,1,2,3,3,4,5,6,6];
const zs = [0,1,2,3,4,5,6,7,8,9];


// here we go

console.log( unionn(xs, ys, zs) );

It turns out unionn is just foldl (aka Array.prototype.reduce), which takes union as its reducer. Note: Since the implementation doesn't use an additional accumulator, it will throw an error when you apply it without arguments.

Grime answered 5/9, 2016 at 19:37 Comment(5)
a couple feedbacks: I noticed that flip and notf are unused. Also unionBy predicate leaks implementation details (requires implicit knowledge of Set type). It might be nice if you could just do something like this: union = unionBy (apply) and unionci = unionBy (p => x => p(x.toLowerCase())). That way the user just sends whatever the grouping value is to p – just an idea ^_^Guyot
zs variable declaration also lacks var/let keywordGuyot
here's a code snippet to clarify [gist: unionBy.js]Guyot
@naomik After rethinking my solution for a while I am not so sure anymore if it is the right way to pass the predicate. All you gain is a transformation of each element of the second array. I wonder if this approach solves more than just toy problems.Grime
what are the benefits of functional approach in this case?Rampage
S
4

If you do not want duplicates of a specific property (for example the ID)

let noDuplicate = array1.filter ( i => array2.findIndex(a => i.id==a.id)==-1 );
let result = [...noDuplicate, ...array2];
Stomachic answered 14/11, 2018 at 15:7 Comment(0)
B
4

var array1 = ["one","two"];
var array2 = ["two", "three"];
var collectionOfTwoArrays = [...array1, ...array2];    
var uniqueList = array => [...new Set(array)];
console.log('Collection :');
console.log(collectionOfTwoArrays);    
console.log('Collection without duplicates :');
console.log(uniqueList(collectionOfTwoArrays));
Bernadinebernadotte answered 7/1, 2019 at 12:21 Comment(0)
P
4

Here an option for objects with object arrays:

const a = [{param1: "1", param2: 1},{param1: "2", param2: 2},{param1: "4", param2: 4}]
const b = [{param1: "1", param2: 1},{param1: "4", param2: 5}]


var result = a.concat(b.filter(item =>
         !JSON.stringify(a).includes(JSON.stringify(item))
    ));

console.log(result);
//Result [{param1: "1", param2: 1},{param1: "2", param2: 2},{param1: "4", param2: 4},{param1: "4", param2: 5}]
Packing answered 29/3, 2020 at 18:24 Comment(0)
S
3

for the sake of it... here is a single line solution:

const x = [...new Set([['C', 'B'],['B', 'A']].reduce( (a, e) => a.concat(e), []))].sort()
// ['A', 'B', 'C']

Not particularly readable but it may help someone:

  1. Applies a reduce function with the initial accumulator value set to an empty array.
  2. The reduce function uses concat to append each sub-array onto the accumulator array.
  3. The result of this is passed as a constructor parameter to create a new Set.
  4. The spread operator is used to convert the Set to an array.
  5. The sort() function is applied to the new array.
Stereometry answered 3/12, 2017 at 21:48 Comment(1)
Also instead of reduce() you can use Array.from(set)Rubicon
A
3
var arr1 = [1, 3, 5, 6];
var arr2 = [3, 6, 10, 11, 12];
arr1.concat(arr2.filter(ele => !arr1.includes(ele)));
console.log(arr1);

output :- [1, 3, 5, 6, 10, 11, 12]
Appealing answered 25/9, 2018 at 8:54 Comment(0)
G
3

You can try this:

const union = (a, b) => Array.from(new Set([...a, ...b]));

console.log(union(["neymar","messi"], ["ronaldo","neymar"]));
Guidance answered 5/2, 2019 at 10:22 Comment(0)
A
3

The simplest solution with filter:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];

var mergedArrayWithoutDuplicates = array1.concat(
  array2.filter(seccondArrayItem => !array1.includes(seccondArrayItem))
);
Alight answered 7/3, 2019 at 8:57 Comment(0)
P
3

Modular, General

This could be achieved by composing two essential functions.

const getUniqueMerge = (...arrs) => getUniqueArr(mergeArrs(...arrs))
const getUniqueArr = (array) => Array.from(new Set(array))  
const mergeArrs = (...arrs) => [].concat(...arrs)

It can handle unlimited arrays, or values

console.log(getUniqueMerge(["Vijendra","Singh"],["Singh", "Shakya"])
// ["Vijendra", "Singh", "Shakya"]

console.log(getUniqueMerge(["Sheldon", "Cooper"], ["and", "Cooper", "Amy", "and"], "Farrah", "Amy", "Fowler"))
// ["Sheldon", "Cooper", "and", "Amy", "Farrah", "Fowler"]
Palatal answered 22/4, 2019 at 18:1 Comment(0)
M
3

If you merging object arrays, consider use of lodash UnionBy function, it allows you to set custom predicate compare objects:

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);

Result is: [{ a: 1; b: 2 }, { a: 2; b: 4 }]

First passed match from arrays is used in result

Marc answered 10/3, 2020 at 14:10 Comment(1)
Thank you. It is the best solution, I am sure.Coagulate
G
3
  1. Using array.concat() and array.filter()
  2. Using new Set object and Spread Operator
  3. Using array.concat and new Set object

let array1 = [1, 2, 3, 4, 5]
let array2 = [1, 4, 6, 9]

// Using array.concat and array.filter
const array3 = array1.concat(array2.filter((item)=> array1.indexOf(item) == -1 ))
console.log('array3 : ', array3);

// Using new Set and Spread Operator
const array4 = [...new Set([...array1 ,...array2])];
console.log('array4 : ', array4);

// Using array.concat and new Set
const array5 = [...new Set(array1.concat(array2))];
console.log('array5 : ', array5);
Geronimo answered 6/5, 2022 at 10:28 Comment(0)
K
2

In Dojo 1.6+

var unique = []; 
var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = array1.concat(array2); // Merged both arrays

dojo.forEach(array3, function(item) {
    if (dojo.indexOf(unique, item) > -1) return;
    unique.push(item); 
});

Update

See working code.

http://jsfiddle.net/UAxJa/1/

Kimberliekimberlin answered 3/11, 2011 at 18:28 Comment(3)
Why use dojo just for the forEach function?Carsick
Also, you don't need to merge the too arrays. Just loop through the second array and add their values if they don't exist in the first array.Carsick
@MészárosLajos No, I would never load Dojo just for the forEach function. I posted this in case someone was already using Dojo. As for the optimization, it's not possible unless you know that the first array contains unique values.Kimberliekimberlin
V
2

Merge an unlimited number of arrays or non-arrays and keep it unique:

function flatMerge() {
    return Array.prototype.reduce.call(arguments, function (result, current) {
        if (!(current instanceof Array)) {
            if (result.indexOf(current) === -1) {
                result.push(current);
            }
        } else {
            current.forEach(function (value) {
                console.log(value);
                if (result.indexOf(value) === -1) {
                    result.push(value);
                }
            });
        }
        return result;
    }, []);
}

flatMerge([1,2,3], 4, 4, [3, 2, 1, 5], [7, 6, 8, 9], 5, [4], 2, [3, 2, 5]);
// [1, 2, 3, 4, 5, 7, 6, 8, 9]

flatMerge([1,2,3], [3, 2, 1, 5], [7, 6, 8, 9]);
// [1, 2, 3, 5, 7, 6, 8, 9]

flatMerge(1, 3, 5, 7);
// [1, 3, 5, 7]
Voiceful answered 20/3, 2014 at 18:2 Comment(0)
W
2

Here is about the most effective one, in terms of computation time. Also it keeps the initial order of elements.

First filter all duplicates from second array, then concatenate what is left to the first one.

var a = [1,2,3];
var b = [5,4,3];
var c = a.concat(b.filter(function(i){
    return a.indexOf(i) == -1;
}));
console.log(c); // [1, 2, 3, 5, 4]

Here is slightly improved (faster) version of it, with a downside, that arrays must not miss values:

var i, c = a.slice(), ci = c.length;
for(i = 0; i < b.length; i++){
    if(c.indexOf(b[i]) == -1)
        c[ci++] = b[i];
}
Whippet answered 12/6, 2014 at 8:25 Comment(2)
I don't see why this should be more time efficient than LiraNuna's solution. You both use the concat function, and to find unique elements you both have a time complexity of O(n^2). Your solution is, however, fewer lines of code and easier to read.Garretgarreth
@AntonGildebrand More useless iterations there. You can check out the comparsion here(open browser console to see): jsbin.com/wabahuha/1/edit?js,outputWhippet
M
2

Assuming original arrays don't need de-duplication, this should be pretty fast, retain original order, and does not modify the original arrays...

function arrayMerge(base, addendum){
    var out = [].concat(base);
    for(var i=0,len=addendum.length;i<len;i++){
        if(base.indexOf(addendum[i])<0){
            out.push(addendum[i]);
        }
    }
    return out;
}

usage:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
var array3 = arrayMerge(array1, array2);

console.log(array3);
//-> [ 'Vijendra', 'Singh', 'Shakya' ]
Maharani answered 8/2, 2016 at 23:27 Comment(0)
M
2

looks like the accepted answer is the slowest in my tests;

note I am merging 2 arrays of objects by Key

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<button type='button' onclick='doit()'>do it</button>
<script>
function doit(){
    var items = [];
    var items2 = [];
    var itemskeys = {};
    for(var i = 0; i < 10000; i++){
        items.push({K:i, C:"123"});
        itemskeys[i] = i;
    }

    for(var i = 9000; i < 11000; i++){
        items2.push({K:i, C:"123"});
    }

    console.time('merge');
    var res = items.slice(0);

    //method1();
    method0();
    //method2();

    console.log(res.length);
    console.timeEnd('merge');

    function method0(){
        for(var i = 0; i < items2.length; i++){
            var isok = 1;
            var k = items2[i].K;
            if(itemskeys[k] == null){
                itemskeys[i] = res.length;
                res.push(items2[i]);
            }
        }
    }

    function method1(){
        for(var i = 0; i < items2.length; i++){
            var isok = 1;
            var k = items2[i].K;

            for(var j = 0; j < items.length; j++){
                if(items[j].K == k){
                    isok = 0;
                    break;
                }
            }

            if(isok) res.push(items2[i]);
        }  
    }

    function method2(){
        res = res.concat(items2);
        for(var i = 0; i < res.length; ++i) {
            for(var j = i+1; j < res.length; ++j) {
                if(res[i].K === res[j].K)
                    res.splice(j--, 1);
            }
        }
    }
}
</script>
</body>
</html>
Marksman answered 15/4, 2016 at 19:22 Comment(0)
B
2

The easiest way to do this is either to use concat() to merge the arrays and then use filter() to remove the duplicates, or to use concat() and then put the merged array inside a Set().

First way:

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]

Second way (but with performance implications on the UI):

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);
Berner answered 2/12, 2016 at 14:11 Comment(3)
Really tempted to use the second way but creating a new Set could be costly when doing this in UI update loop.Ramses
I wasn't aware of that. Thanks for pointing out the issue - I'll update my answer. Could you please provide a link in regards to that btw?Berner
Uh I dont think there is a link. I am just saying that based on my own experience working with arrays in the rendering loop in HTML5 canvas.Ramses
H
2

Using Lodash

I found @GijsjanB's answer useful but my arrays contained objects that had many attributes, so I had to de-duplicate them using one of the attributes.

Here's my solution using lodash

userList1 = [{ id: 1 }, { id: 2 }, { id: 3 }]
userList2 = [{ id: 3 }, { id: 4 }, { id: 5 }]
// id 3 is repeated in both arrays

users = _.unionWith(userList1, userList2, function(a, b){ return a.id == b.id });

// users = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }]

The function you pass as the third parameter has two arguments (two elements), and it must return true if they are equal.

Heehaw answered 9/9, 2017 at 22:33 Comment(0)
D
2

You can use loadash unionWith - _.unionWith([arrays], [comparator])

This method is like _.union except that it accepts comparator which is invoked to compare elements of arrays. Result values are chosen from the first array in which the value occurs. The comparator is invoked with two arguments: (arrVal, othVal).

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
 
var array3 = _.unionWith(array1, array2, _.isEqual);
console.log(array3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Dingdong answered 5/11, 2018 at 7:15 Comment(2)
dublicates already answered by same way https://mcmap.net/q/45022/-how-to-merge-two-arrays-in-javascript-and-de-duplicate-itemsMarc
@Marc this answer is not the same - it's improvementRampage
L
2

Reduce them !!!

This alternative instead of merging and deduplicating explicitly it will take one array and reduce it with another array so that each value of the first array can be iterated and destructured in an accumulative behavior, ignoring the already included values by exploiting the persistence of the array because of the recursiveness.

array2.reduce(reducer, array1.reduce(reducer, []))

Test Example:

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

Conclusion

By far more elegant and useful when boring for-each approach wants to be avoided (not that it is not useful).

Deals with the concat() limitations on deduplication.

No need for external libraries like Underscore.js, JQuery or Lo-Dash, nor the trouble to create any built-in function to achieve the desired merged and deduplicated effect.

Oh, and HEY!, it can be done as a one-liner!!!


This answered was possible thanks to ES5 (ECMAScript 2015), beautiful include() and gorgeous reduce().

Leftwards answered 30/10, 2019 at 23:52 Comment(0)
T
2

Here is another neat solution using Set:

const o1 = {a: 1};
const arr1 = ['!@#$%^&*()', 'gh', 123, o1, 1, true, undefined, null];
const arr2 = ['!@#$%^&*()', 123, 'abc', o1, 0x001, true, void 0, 0];

const mergeUnique = (...args) => [ ...new Set([].concat(...args)) ];

console.log(mergeUnique(arr1, arr2));
Tiltyard answered 8/4, 2021 at 15:27 Comment(0)
C
2

Care about efficiency, yet want to do it inline

const s = new Set(array1);
array2.forEach(a => s.add(a));
const merged_array = [...s]; // optional: convert back in array type
Catholicism answered 9/7, 2021 at 6:47 Comment(0)
S
1

Here is a simple example:

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"]));

We define unique(array) to remove redundant elements and use the concat function to combine two arrays.

Subclass answered 25/4, 2015 at 7:15 Comment(0)
C
1

This is my second answer, but I believe the fastest? I'd like someone to check for me and reply in the comments.

My first attempt hit about 99k ops/sec and this go around is saying 390k ops/sec vs the other leading jsperf test of 140k (for me).

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26

I tried to minimize as much array interaction as possible this time around and it looked like I netted some performance.

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;
}

Edit: I made some changes to my function, and the performance is drastic compared to others on the jsperf site.

Confederacy answered 20/8, 2015 at 3:16 Comment(0)
D
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 });
}

Leveraging dictionaries and Jquery you could merge the two arrays and not get duplicates. In my example I'm using a given field on the object but could be just the object itself.

Dahl answered 14/2, 2017 at 21:27 Comment(0)
U
1

Another approach for your review with reduce func:

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"];
Unitarian answered 28/3, 2017 at 13:53 Comment(0)
F
1

If you want to check for unique objects, then use JSON.stringify in your comparison.

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(JSON.stringify(a[i]) === JSON.stringify(a[j]))
                a.splice(j--, 1);
        }
    }

    return a;
}
Fraught answered 7/5, 2017 at 22:29 Comment(0)
Y
1
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);    
}
Yalonda answered 31/5, 2017 at 22:32 Comment(0)
C
1

One line solution as a segue to LiraNuna's:

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);
Cluck answered 1/8, 2017 at 1:18 Comment(0)
T
1

ES2019

You can use it like union(array1, array2, array3, ...)

/**
 * Merges two or more arrays keeping unique items. This method does
 * not change the existing arrays, but instead returns a new array.
 */
function union<T>(...arrays: T[]) {
  return [...new Set([...arrays].flat())];
}

It is ES2019 because of the flat() function, but you can use core-js to get it as a polyfill. The T here is TypeScript generic type, that you can remove if you are not using TypeScript. If you are using TypeScript, make sure to add "lib": ["es2019.array"] to compiler options in tsconfig.json.

or...

just use lodash _.union

Trifid answered 18/8, 2019 at 19:5 Comment(2)
regarding union<T>(...arrays: T[]) - is this JavaScript/ES2019?Hakodate
@Hakodate no, but flat() is. Please read the description in the post.Trifid
S
1

For n arrays, you can get the union like so.

function union(arrays) {
    return new Set(arrays.flat()).keys();
};
Stung answered 30/11, 2020 at 14:40 Comment(1)
almost, but not quite: Set.keys() (an "alias" for Set.values() ) returns a set iterator, which is not an array, as asked for.Hakodate
C
1

Built a tester to check just how fast some of the performance oriented answers are. Feel free to add some more. So far, Set is both the simplest and fastest option (by bigger margins as the number of records increases), at least with simple Number types.

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');
}
Canst answered 10/2, 2021 at 0:50 Comment(2)
It seems there is a high sensibility to the number of items. For less than 400 items, on my machine (Mac with Chrome), Method 1 is fastest. For more, Method 3 is fastest. But since for small numbers performance is not important, and considering that Method 3 is by far the simplest to read, it should effectively be the recommended method.Interweave
I tested by replacing Numbers by Strings of text. And the result is still the same: method 1 is faster for small datasets (less than 50 items with the Strings), and Set is incredibly faster when size increase. gist.github.com/Pitouli/3165d59ae3a1fb90bf35ee7dbbebc28fInterweave
C
1

To offer something simpler and more elegant, in this day and age, using an existing library:

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']

It is both high performance, as we are iterating only once, and the code is very easy to read.

P.S. I'm the author of iter-ops.

Cauthen answered 23/11, 2021 at 1:4 Comment(1)
I'm trying this out, thanks for the lib broOtila
H
1

Using Array.prototype.flat():

const input = [
  [1, 2, 3, 1],
  [101, 2, 1, 10],
  [2, 1]
];

const union = (arr) => {
  return [  ...new Set( arr.flat() )  ];
}

console.log('output', union(input));
Hakodate answered 21/9, 2023 at 8:13 Comment(0)
A
1

We can concat method use to add two or more array

array1.concat(array2, array3, ..., arrayX)

// unique remove duplicates of array

console.log([...new Set([1, 2, 4, 4, 3])]); // [1, 2, 4, 3]
Arras answered 13/10, 2023 at 11:2 Comment(0)
B
0

Here is my solution https://gist.github.com/4692150 with deep equals and easy to use result:

function merge_arrays(arr1,arr2)
{
   ... 
   return {first:firstPart,common:commonString,second:secondPart,full:finalString}; 
}

console.log(merge_arrays(
[
[1,"10:55"] ,
[2,"10:55"] ,
[3,"10:55"]
],[
[3,"10:55"] ,
[4,"10:55"] ,
[5,"10:55"]
]).second);

result:
[
[4,"10:55"] ,
[5,"10:55"]
]
Buell answered 1/2, 2013 at 16:1 Comment(0)
M
0

Just wrote before for the same reason (works with any amount of arrays):

/**
 * Returns with the union of the given arrays.
 *
 * @param Any amount of arrays to be united.
 * @returns {array} The union array.
 */
function uniteArrays()
{
    var union = [];
    for (var argumentIndex = 0; argumentIndex < arguments.length; argumentIndex++)
    {
        eachArgument = arguments[argumentIndex];
        if (typeof eachArgument !== 'array')
        {
            eachArray = eachArgument;
            for (var index = 0; index < eachArray.length; index++)
            {
                eachValue = eachArray[index];
                if (arrayHasValue(union, eachValue) == false)
                union.push(eachValue);
            }
        }
    }

    return union;
}    

function arrayHasValue(array, value)
{ return array.indexOf(value) != -1; }
Marler answered 5/1, 2014 at 2:9 Comment(0)
L
0

This is simple and can be done in one line with jQuery:

var arr1 = ['Vijendra', 'Singh'], arr2 =['Singh', 'Shakya'];

$.unique(arr1.concat(arr2))//one line

["Vijendra", "Singh", "Shakya"]
Lotta answered 7/11, 2014 at 2:19 Comment(1)
From jQuery documentation "Note that this only works on arrays of DOM elements, not strings or numbers." (api.jquery.com/jQuery.unique). The method has been deprecated.Roofdeck
Y
0
Array.prototype.pushUnique = function(values)
{
    for (var i=0; i < values.length; i++)
        if (this.indexOf(values[i]) == -1)
            this.push(values[i]);
};

Try:

var array1 = ["Vijendra","Singh"];
var array2 = ["Singh", "Shakya"];
array1.pushUnique(array2);
alert(array1.toString());  // Output: Vijendra,Singh,Shakya
Ywis answered 18/4, 2015 at 1:49 Comment(0)
H
0

If, like me, you need to support older browsers, this works with IE6+

function es3Merge(a, b) {
    var hash = {},
        i = (a = a.slice(0)).length,
        e;

    while (i--) {
        hash[a[i]] = 1;
    }

    for (i = 0; i < b.length; i++) {
        hash[e = b[i]] || a.push(e);
    }

    return a;
};

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/22

Hexane answered 4/6, 2015 at 23:23 Comment(0)
C
0

I came across this post when trying to do the same thing, but I wanted to try something different. I just made up the function below. I also had another variable, 'compareKeys', (array of keys) for doing shallow object comparison. I'm going to probably change it to a function in the future.

Anyway, I didn't include that part, because it doesn't apply to the question. I also put my code into the jsperf going around. Edited: I fixed my entry in jsperf. My function gets about 99k ops/sec compared to 140k.

To the code: I first make an array of the available indices and then eliminate them by iterating over the first array. Finally, I push in the 'left-overs' by using the trimmed down array of indices that didn't match between the two arrays.

http://jsperf.com/merge-two-arrays-keeping-only-unique-values/26

function indiceMerge(a1, a2) {
    var ai = [];
    for (var x = 0; x < a2.length; x++) {
        ai.push(x)
    };

    for (var x = 0; x < a1.length; x++) {
        for (var y = 0; y < ai.length; y++) {
            if (a1[x] === a2[ai[y]]) {
                ai.splice(y, 1);
                y--;
            }
        }
    }

    for (var x = 0; x < ai.length; x++) {
        a1.push(a2[ai[x]]);
    }

    return a1;
}
Confederacy answered 20/8, 2015 at 2:34 Comment(2)
What does this do that's different?Bandung
I wrote it with performance in mind. There are many ways to do what the OP wants, but performance is usually overlooked. You can check it out link for an updated one, three years later. @BandungConfederacy
C
0

Usage: https://gist.github.com/samad-aghaei/7250ffb74ed80732debb1cbb14d2bfb0

var _uniqueMerge = function(opts, _ref){
    for(var key in _ref)
        if (_ref && _ref[key] && _ref[key].constructor && _ref[key].constructor === Object)
          _ref[key] = _uniqueMerge((opts ? opts[key] : null), _ref[key] );
        else if(opts && opts.hasOwnProperty(key))
          _ref[key] = opts[key];
        else _ref[key] = _ref[key][1];
    return _ref;
}
Crying answered 5/5, 2017 at 0:10 Comment(0)
G
0

The best and simplest way to do that is using the function "some()" of JavaScript that returns true or false indicating if the array contains the object's element. You can make this:

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);

The results:

["Vijendra", "Singh", "Shakya"]

ss you wish... without duplicate it...

Gerenuk answered 12/5, 2017 at 21:25 Comment(1)
What does "ss you wish" mean?Corinacorine
H
0
var a = [1,2,3]
var b = [1,2,4,5]

I like one liners. This will push distinct b elements to a

b.forEach(item => a.includes(item) ? null : a.push(item));

And another version that will not modify a

var c = a.slice();
b.forEach(item => c.includes(item) ? null : c.push(item));
Hord answered 19/5, 2018 at 1:3 Comment(0)
C
0

If you're purely using underscore.js, it doesn't have unionWith, unionBy

you can try out : _.uniq(_.union(arr1, arr2), (obj) => obj.key) ( key is the key param of each object ) this should help to get unique after union of both arrays.

Conformist answered 21/12, 2018 at 23:13 Comment(0)
A
0

I think this works faster.

removeDup = a => {

    for (let i = a.length - 1; i >= 0; i--) {
        for (let j = i-1; j >= 0; j--) {
            if (a[i] === a[j])
                a.splice(j--, 1);
        }
    }

    return a;
}
Alysa answered 26/4, 2019 at 10:15 Comment(0)
H
0
   //1.merge two array into one array

   var arr1 = [0, 1, 2, 4];
   var arr2 = [4, 5, 6];

   //for merge array we use "Array.concat"

   let combineArray = arr1.concat(arr2); //output

   alert(combineArray); //now out put is 0,1,2,4,4,5,6 but 4 reapeat

   //2.same thing with "Spread Syntex"

   let spreadArray = [...arr1, ...arr2];

   alert(spreadArray);  //now out put is 0,1,2,4,4,5,6 but 4 reapete


   /*
       if we need remove duplicate element method use are
       1.Using set
       2.using .filter
       3.using .reduce
   */
Helio answered 24/11, 2019 at 15:1 Comment(0)
U
0

Not Performant if you have extremely large lists, and this isnt for merging since many solutions already have been documented, but i solved my problems with this solution (since most solutions of array filtering apply to simple arrays)

const uniqueVehiclesServiced = 
  invoice.services.sort().filter(function(item, pos, ary) {
    const firstIndex = invoice.services.findIndex((el, i, arr) => el.product.vin === item.product.vin)

  return !pos || firstIndex == pos;
});
Underbred answered 8/12, 2021 at 22:10 Comment(0)
R
0

I have a similar request but it is with Id of the elements in the array.

And, here is the way I do the deduplication.

It is simple, easy to maintain, and good to use.

// Vijendra's Id = Id_0
// Singh's Id = Id_1
// Shakya's Id = Id_2

let item0 = { 'Id': 'Id_0', 'value': 'Vijendra' };
let item1 = { 'Id': 'Id_1', 'value': 'Singh' };
let item2 = { 'Id': 'Id_2', 'value': 'Shakya' };

let array = [];

array = [ item0, item1, item1, item2 ];

let obj = {};
array.forEach(item => {
    obj[item.Id] = item;
});

let deduplicatedArray = [];
let deduplicatedArrayOnlyValues = [];
for(let [index, item] of Object.values(obj).entries()){
    deduplicatedArray = [ ...deduplicatedArray, item ];
    deduplicatedArrayOnlyValues = [ ...deduplicatedArrayOnlyValues , item.value ];
};
    
console.log( JSON.stringify(array) );
console.log( JSON.stringify(deduplicatedArray) );
console.log( JSON.stringify(deduplicatedArrayOnlyValues ) );

The console log

[{"recordId":"Id_0","value":"Vijendra"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_2","value":"Shakya"}]

[{"recordId":"Id_0","value":"Vijendra"},{"recordId":"Id_1","value":"Singh"},{"recordId":"Id_2","value":"Shakya"}]

["Vijendra","Singh","Shakya"]
Ringmaster answered 23/1, 2022 at 5:44 Comment(0)
K
0

return an array of unique objects from arrays...

function uniqueObjectArray(baseArray, mergeArray) {
    // we can't compare unique objects within an array ~es6...
    // ...e.g. concat/destructure/Set()
    // so we'll create a mapping of: item.id* for each -> item
    const uniqueMap = new Map()
    const uniqueArray = []

    // hash array items by id*
    baseArray.forEach(item => !uniqueMap.has(item.id) && uniqueMap.set(item.id, item))
    mergeArray.forEach(item => !uniqueMap.has(item.id) && uniqueMap.set(item.id, item))

    // hash -> array
    uniqueMap.forEach(item => uniqueArray.push(item))
    return uniqueArray
}
Kv answered 30/3, 2023 at 4:20 Comment(0)
C
0

My quick take

const arePropsEqualDefault = (oldProps, newProps) => {
  const uniqueKeys = Object.values({...Object.keys(oldProps), ...Object.keys(newProps)});
  for (const key in uniqueKeys) {
    console.log(Object.is(oldProps[key], newProps[key]))
    if (!Object.is(oldProps[key], newProps[key])) return false;
  }
  return true;
}
Corydon answered 27/1 at 10:0 Comment(0)
G
-1

This is the function I use when I need to merge, (or return the union of) two arrays.

var union = function (a, b) {
  for (var i = 0; i < b.length; i++)
    if (a.indexOf(b[i]) === -1)
      a.push(b[i]);
  return a;
};

var a = [1, 2, 3, 'a', 'b', 'c'];
var b = [2, 3, 4, 'b', 'c', 'd'];

a = union(a, b);
//> [1, 2, 3, "a", "b", "c", 4, "d"]

var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];

var array3 = union(array1, array2);
//> ["Vijendra", "Singh", "Shakya"]
Grith answered 19/4, 2014 at 20:9 Comment(0)
Y
-1
function set(a, b) {
  return a.concat(b).filter(function(x,i,c) { return c.indexOf(x) == i; });
}
Yanirayank answered 6/6, 2014 at 1:40 Comment(0)
R
-1

This is fast, collates any number of arrays, and works with both numbers and strings.

function collate(a){ // Pass an array of arrays to collate into one array
    var h = { n: {}, s: {} };
    for (var i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++)
        (typeof a[i][j] === "number" ? h.n[a[i][j]] = true : h.s[a[i][j]] = true);
    var b = Object.keys(h.n);
    for (var i=0; i< b.length; i++)
        b[i]=Number(b[i]);
    return b.concat(Object.keys(h.s));
}

> a = [ [1,2,3], [3,4,5], [1,5,6], ["spoon", "fork", "5"] ]
> collate( a )

[1, 2, 3, 4, 5, 6, "5", "spoon", "fork"]

If you don't need to distinguish between 5 and "5", then

function collate(a){
    var h = {};
    for (i=0; i < a.length; i++) for (var j=0; j < a[i].length; j++)
        h[a[i][j]] = typeof a[i][j] === "number";
    for (i=0, b=Object.keys(h); i< b.length; i++)
        if (h[b[i]])
            b[i]=Number(b[i]);
    return b;
}
[1, 2, 3, 4, "5", 6, "spoon", "fork"]

will do.

And if you don't mind (or would prefer) all values ending up as strings anyway then just this:

function collate(a){
    var h = {};
    for (var i=0; i < a.length; i++)
        for (var j=0; j < a[i].length; j++)
            h[a[i][j]] = true;
    return Object.keys(h)
}
["1", "2", "3", "4", "5", "6", "spoon", "fork"]

If you don't actually need an array, but just want to collect the unique values and iterate over them, then (in most browsers (and node.js)):

h = new Map();
for (i=0; i < a.length; i++)
    for (var j=0; j < a[i].length; j++)
        h.set(a[i][j]);

It might be preferable.

Rerun answered 12/2, 2016 at 17:33 Comment(1)
Thank you so much. In synchronous jQuery operations this was that variation that worked for me for inline generated arrays.Cottonwood
D
-1

Better option for large inputs will be to sort arrays. Then merge them.

function sortFunction(a, b) {
        return a - b;
}

arr1.sort(sortFunction);
arr2.sort(sortFunction);

function mergeDedup(arr1, arr2) {

    var i = 0, j = 0, result = [];
    while (i < arr1.length && j < arr2.length) {

        if (arr1[i] < arr2[j]) {
            writeIfNotSameAsBefore(result, arr1[i]);
            i++;
        }
        else if (arr1[i] > arr2[j]) {
            writeIfNotSameAsBefore(result, arr2[j]);
            j++;
        }
        else {
            writeIfNotSameAsBefore(result, arr1[i]);
            i++;
            j++;
        }

    }

    while (i < arr1.length) {
        writeIfNotSameAsBefore(result, arr1[i]);
        i++;
    }

    while (j < arr2.length) {
        writeIfNotSameAsBefore(result, arr2[j]);
        j++;
    }
    return result;
}

function writeIfNotSameAsBefore(arr, item) {
    if (arr[arr.length - 1] !== item) {
        arr[arr.length] = item;
    }
    return arr.length;
}

Sorting will take O(nlogn + mlogm), where n and m are length of the arrays, and O(x) for merging, where x = Max(n, m);

Discriminate answered 25/8, 2016 at 10:1 Comment(0)
L
-1

You can merge the results and filter the duplicates:

let combinedItems = [];

// items is an Array of arrays: [[1,2,3],[1,5,6],...]    
items.forEach(currItems => {
    if (currItems && currItems.length > 0) {
        combinedItems = combinedItems.concat(currItems);
    }
});

let noDuplicateItems = combinedItems.filter((item, index) => {
    return !combinedItems.includes(item, index + 1);
});
Liar answered 9/8, 2017 at 10:16 Comment(0)
E
-1

/**
 * De-duplicate an array keeping only unique values.
 * Use hash table (js object) to filter-out duplicates.
 * The order of array elements is maintained.
 * This algorithm is particularly efficient for large arrays (linear time).
 */
function arrayUniqueFast(arr) {
	var seen = {};
	var result = [];
	var i, len = arr.length;
	for (i = 0; i < len; i++) {
		var item = arr[i];
		// hash table lookup
		if (!seen[item]) {
			result.push(item);
			seen[item] = true;
		}
	}
	return result;
}

///// test
var array1 = ["Vijendra", "Singh"];
var array2 = ["Singh", "Shakya"];

var result = arrayUniqueFast(array1.concat(array2));
document.write('<br>result: ' + result);

For other methods to dedup an array, please see my benchmarks at: https://jsperf.com/de-duplicate-an-array-keeping-only-unique-values

Entitle answered 18/9, 2017 at 19:15 Comment(0)
R
-1

I learned a cheeky little way to concatenate two arrays with the spread operator:

var array1 = ['tom', 'dick', 'harry'];
var array2 = ['martin', 'ricky'];

array1.push(...array2);

The "..." spread operator splits the following array into individual items and then push can handle them as separate arguments.

Repentance answered 8/3, 2018 at 4:4 Comment(1)
interesting, but less readable than .concat() and doesn't resolve duplication issueRoodepoortmaraisburg
P
-1

Given two sorted arrays of simple types without duplicates, this will merge them in O(n) time, and the output will be also sorted.

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++]);
        }
    }
}
Pori answered 3/1, 2019 at 20:0 Comment(2)
What's different about this from the accepted answer and several other ~20 lines of raw JS answers?Bandung
@Bandung it's different because, as I said in the description, it takes "sorted arrays of simple types" and it is pretty good because it is portable and O(n) which is faster than answers O(n^2). but no worries. i don't object to the down-vote!Pori
E
-2

Use:

Array.prototype.merge = function (arr) {
    var key;
    for(key in arr) 
        this[key] = arr[key];
};
Ellison answered 27/9, 2013 at 23:48 Comment(2)
This doesn't merge arrays—this just overwrites one with another. E.g., var f = [1]; f.merge([2]);Lugansk
Hmmm... but I thought the keys that are already there stay, and you want the new ones and the merged one to overwrite? Oh maybe I was thinking dictionaries or something.Ellison
N
-2

const merge(...args)=>(new Set([].concat(...args)))

Nitrobenzene answered 8/5, 2016 at 10:25 Comment(1)
Of coruse if you want to return an array then just use Array.from(merge(arguments))Nitrobenzene

© 2022 - 2024 — McMap. All rights reserved.