Question

Merge and De-duplicate Arrays in JavaScript with Set

javascriptarraysmerge

Question

Given two JavaScript arrays:

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

How can they be merged into a single array that removes repeated values while preserving the order in which values first appear?

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

Short Answer

You will learn how to combine arrays with the spread operator and remove duplicate primitive values with Set. You will also learn how insertion order works, how to handle duplicates in objects, and which alternatives are useful in older or more specialized code.

Concept

An array stores an ordered list of values. Merging arrays means placing the values from one array after the values from another array.

JavaScript's Set is a collection that stores each value only once. When values are added to a Set, it retains the order in which each unique value was first added.

That makes this pattern useful:

const uniqueValues = [...new Set([...array1, ...array2])];

It works in two stages:

  1. [...array1, ...array2] creates one combined array.
  2. new Set(...) removes repeated values, keeping the first occurrence.
  3. [...set] turns the Set back into a normal array.

This matters in real programs because duplicate data often appears when combining user selections, API results, configuration values, tags, permissions, or search results.

Mental Model

Imagine two guest lists being added to one sign-in sheet.

  • Write every name from the first list, then every name from the second list.
  • Before writing a name, check whether it is already on the sign-in sheet.
  • If it is already there, skip it.

A Set behaves like that sign-in sheet: it remembers which values have already appeared and keeps the first-seen order.

Take Quiz

Syntax and Examples

Use the spread operator (...) to merge arrays and a Set to retain unique values.

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

const array3 = [...new Set([...array1, ...array2])];

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

[...array1, ...array2] produces this intermediate array:

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

The Set sees "Singh" a second time and does not add another copy. Finally, spreading the Set into [] creates an array again.

A reusable function

function mergeUnique(first, second) {
  return [...new Set([...first, ...second])];
}

console.log(mergeUnique([1, 2, 3], [3, 4, 2]));
// [1, 2, 3, 4]

The original input arrays are not changed.

Step by Step Execution

Consider this code:

const first = ["red", "blue"];
const second = ["blue", "green"];
const result = [...new Set([...first, ...second])];

Execution trace:

  1. ...first contributes "red" and "blue".

  2. ...second contributes "blue" and "green".

  3. The combined array becomes:

    ["red", "blue", "blue", "green"]
    
  4. new Set(...) processes values from left to right:

    • Add "red".
    • Add "blue".
    • Ignore the second "blue" because it is already present.
    • Add "green".
  5. The Set contains values in insertion order: "red", "blue", "green".

  6. [...set] converts those values into:

    ["red", "blue", "green"]
    

Real World Use Cases

  • Tag selection: Combine tags suggested by an API with tags selected by a user, without displaying the same tag twice.
  • Permissions: Merge permissions inherited from a team with permissions assigned directly to a user.
  • Search results: Combine results from multiple sources while preventing repeated IDs or strings.
  • Navigation items: Merge default menu entries and feature-specific entries.
  • Data cleanup scripts: Remove repeated values from imported CSV or JSON data.
  • Configuration: Combine lists of enabled modules from base and environment-specific settings.
Take Quiz

Real Codebase Usage

In production code, developers usually wrap the operation in a named function when it represents a business rule.

function mergeUniqueTags(defaultTags, userTags) {
  return [...new Set([...defaultTags, ...userTags])];
}

Validate inputs at a boundary

If values may come from an API or user input, verify that they are arrays before merging:

function mergeUnique(first, second) {
  if (!Array.isArray(first) || !Array.isArray(second)) {
    throw new TypeError("Both arguments must be arrays.");
  }

  return [...new Set([...first, ...second])];
}

Merge objects by an identifier

Set does not de-duplicate separately created objects with identical properties. In codebases, objects are commonly de-duplicated by an ID using a Map:

function mergeUsersById(first, second) {
  const usersById = new Map();

  for (const user of [...first, ...second]) {
    if (!usersById.has(user.id)) {
      usersById.set(user.id, user);
    }
  }

  return [...usersById.values()];
}

This keeps the first user object for each id and preserves first-seen order.

Common Mistakes

Using concat alone

concat merges arrays but does not remove duplicates:

const result = array1.concat(array2);
// ["Vijendra", "Singh", "Singh", "Shakya"]

Use Set after merging if uniqueness is required.

Forgetting to convert the Set back to an array

const result = new Set([...array1, ...array2]);

This is a Set, not an array. It does not support array methods such as .map() in the same way. Convert it with:

const result = [...new Set([...array1, ...array2])];

Expecting objects with matching properties to be considered duplicates

const first = [{ id: 1, name: "Ada" }];
const second = [{ id: 1, name: "Ada" }];

const result = [...new Set([...first, ...second])];
console.log(result.length); // 2

These are two different object references. De-duplicate objects by a stable key such as id.

Accidentally changing the input array with push

array1.push(...array2);

This modifies array1 and still leaves duplicates. Prefer a new array when mutation is not intended.

Assuming case-insensitive duplicates are automatic

"Singh" and "singh" are different strings. Normalize strings first if your application treats them as equivalent:

const uniqueLowercase = [...new Set(
  [...array1, ...array2].map(name => name.toLowerCase())
)];

Comparisons

ApproachRemoves duplicatesPreserves first-seen orderChanges input arraysBest use
[...new Set([...a, ...b])]YesYesNoModern JavaScript and primitive values
a.concat(b)NoYesNoMerge only
a.push(...b)NoYesYes, modifies aIntentional in-place merging
a.filter(...) with indexOfYesYesNoOlder environments or custom logic
Map keyed by idYes, by keyYesNoArrays of objects

Set versus Map

  • Use Set when the value itself defines uniqueness, such as strings, numbers, or shared object references.
  • Use Map when an object property, such as id or email, defines uniqueness.

Set versus filter

A Set is usually clearer for straightforward de-duplication. Use filter when the definition of a duplicate requires custom comparison logic.

Take Quiz

Cheat Sheet

// Merge two arrays and retain first-seen unique primitive values
const unique = [...new Set([...array1, ...array2])];

// Merge many arrays
const unique = [...new Set([...array1, ...array2, ...array3])];

// Remove duplicates from one array
const unique = [...new Set(values)];

// Reusable helper
const mergeUnique = (a, b) => [...new Set([...a, ...b])];
  • Set keeps the first insertion of each unique value.
  • The source arrays are not mutated by the spread-based approach.
  • String comparisons are case-sensitive: "A" !== "a".
  • For objects, Set compares object identity, not matching properties.
  • Use a Map or a key-based loop to de-duplicate objects by id, email, or another property.
  • Set treats NaN values as duplicates of each other.

FAQ

How do I merge two arrays and remove duplicates in JavaScript?

Use a Set around a merged array:

const merged = [...new Set([...array1, ...array2])];

Does Set preserve array order in JavaScript?

Yes. A Set iterates values in insertion order, so the output keeps the order in which each unique value first appeared.

Does this modify either original array?

No. The spread operator creates a new combined array, and the final result is another new array.

Can I use this with numbers and strings?

Yes. It works well with primitive values such as strings, numbers, booleans, null, and undefined.

Why does Set not remove duplicate-looking objects?

Objects are compared by reference. Two separate object literals are different values even when their properties are identical. Use an object key such as id to determine duplicates.

How do I keep the last occurrence instead of the first?

Reverse the merged values, create a Set, then reverse the result:

const keepLast = [...new Set([...array1, ...array2].reverse())].reverse();

For object arrays, a Map is often easier because you can explicitly choose whether later values replace earlier ones.

Take Quiz

Mini Project

Description

Build a small utility that combines topic tags from an article and a reader's selected tags. The output should show each tag once, in the order it was first encountered. This mirrors common features in content systems and form interfaces.

Goal

Create a function that merges two tag arrays, removes repeated tags, and returns a new array without changing either input.

Requirements

Requirement 1

Take Quiz

Keep learning

Related questions

View more