Find Unique Numbers
Removing Duplicates
Finding unique numbers (or removing duplicates) is a common programming task. JavaScript provides several approaches with different performance characteristics.
Try Finding Unique Numbers
Code Editor
Console Output
Click "Run" to execute your code...
Method 1: Using Set (Best Method)
// Set automatically removes duplicates
function getUniqueNumbers1(arr) {
return [...new Set(arr)];
}
const numbers = [1, 2, 2, 3, 4, 4, 5, 1, 3];
console.log(getUniqueNumbers1(numbers)); // [1, 2, 3, 4, 5]
// Alternative syntax
function getUniqueNumbers1b(arr) {
return Array.from(new Set(arr));
}
console.log(getUniqueNumbers1b([5, 5, 5, 6, 7, 7])); // [5, 6, 7]
// One-liner
const unique = arr => [...new Set(arr)];
console.log(unique([1, 1, 2, 2, 3, 3])); // [1, 2, 3]
// Works with any array type
const words = ['apple', 'banana', 'apple', 'orange', 'banana'];
console.log([...new Set(words)]); // ['apple', 'banana', 'orange']
// Explanation:
// 1. new Set(arr) - creates Set from array (removes duplicates)
// 2. [...Set] or Array.from(Set) - converts Set back to array
// Performance: O(n) - very fast!Method 2: Using filter and indexOf
function getUniqueNumbers2(arr) {
return arr.filter((num, index) => {
return arr.indexOf(num) === index;
});
}
const numbers = [1, 2, 2, 3, 4, 4, 5];
console.log(getUniqueNumbers2(numbers)); // [1, 2, 3, 4, 5]
// More concise
function getUniqueNumbers2b(arr) {
return arr.filter((num, index) => arr.indexOf(num) === index);
}
console.log(getUniqueNumbers2b([1, 1, 2, 3, 2, 4])); // [1, 2, 3, 4]
// Explanation:
// indexOf returns the FIRST occurrence of an element
// If current index matches first occurrence, it's unique
// Example: [1, 2, 2, 3]
// - index 0: indexOf(1) = 0 ā (keep)
// - index 1: indexOf(2) = 1 ā (keep)
// - index 2: indexOf(2) = 1 ā (remove, duplicate)
// - index 3: indexOf(3) = 3 ā (keep)
// Performance: O(n²) - slower for large arrays
// indexOf is called for each element, and indexOf itself is O(n)Method 3: Using reduce
function getUniqueNumbers3(arr) {
return arr.reduce((unique, num) => {
if (!unique.includes(num)) {
unique.push(num);
}
return unique;
}, []);
}
const numbers = [1, 2, 2, 3, 4, 4, 5];
console.log(getUniqueNumbers3(numbers)); // [1, 2, 3, 4, 5]
// Alternative with ternary
function getUniqueNumbers3b(arr) {
return arr.reduce((unique, num) =>
unique.includes(num) ? unique : [...unique, num],
[]
);
}
console.log(getUniqueNumbers3b([1, 1, 2, 3, 2])); // [1, 2, 3]
// Using object as accumulator (for counting)
function getUniqueWithCount(arr) {
return arr.reduce((acc, num) => {
acc[num] = (acc[num] || 0) + 1;
return acc;
}, {});
}
console.log(getUniqueWithCount([1, 2, 2, 3, 3, 3]));
// { 1: 1, 2: 2, 3: 3 }
// Get unique from the count object
const counts = getUniqueWithCount([1, 2, 2, 3]);
const uniqueNums = Object.keys(counts).map(Number);
console.log(uniqueNums); // [1, 2, 3]
// Performance: O(n²) - includes is O(n) for each elementMethod 4: Using Object/Map as Hash
// Using Object
function getUniqueNumbers4(arr) {
const seen = {};
const result = [];
for (const num of arr) {
if (!seen[num]) {
seen[num] = true;
result.push(num);
}
}
return result;
}
const numbers = [1, 2, 2, 3, 4, 4, 5];
console.log(getUniqueNumbers4(numbers)); // [1, 2, 3, 4, 5]
// Using Map (better for non-string keys)
function getUniqueNumbers4b(arr) {
const seen = new Map();
const result = [];
for (const num of arr) {
if (!seen.has(num)) {
seen.set(num, true);
result.push(num);
}
}
return result;
}
console.log(getUniqueNumbers4b([1, 1, 2, 3, 2])); // [1, 2, 3]
// Get unique and preserve order
function getUniqueOrdered(arr) {
const map = new Map();
for (const num of arr) {
if (!map.has(num)) {
map.set(num, true);
}
}
return Array.from(map.keys());
}
console.log(getUniqueOrdered([3, 1, 2, 1, 3])); // [3, 1, 2]
// Performance: O(n) - very fast, but uses extra memoryMethod 5: Nested Loops (Not Recommended)
// Using nested loops
function getUniqueNumbers5(arr) {
const result = [];
for (let i = 0; i < arr.length; i++) {
let isDuplicate = false;
// Check if already in result
for (let j = 0; j < result.length; j++) {
if (arr[i] === result[j]) {
isDuplicate = true;
break;
}
}
if (!isDuplicate) {
result.push(arr[i]);
}
}
return result;
}
const numbers = [1, 2, 2, 3, 4, 4, 5];
console.log(getUniqueNumbers5(numbers)); // [1, 2, 3, 4, 5]
// Alternative approach
function getUniqueNumbers5b(arr) {
const result = [];
for (const num of arr) {
if (!result.includes(num)) {
result.push(num);
}
}
return result;
}
console.log(getUniqueNumbers5b([1, 1, 2, 3, 2])); // [1, 2, 3]
// Performance: O(n²) - slowest method, avoid for large arraysBonus: Advanced Cases
// Find duplicates (opposite of unique)
function findDuplicates(arr) {
const seen = new Set();
const duplicates = new Set();
for (const num of arr) {
if (seen.has(num)) {
duplicates.add(num);
} else {
seen.add(num);
}
}
return Array.from(duplicates);
}
console.log(findDuplicates([1, 2, 2, 3, 4, 4, 5])); // [2, 4]
// Count occurrences
function countOccurrences(arr) {
return arr.reduce((acc, num) => {
acc[num] = (acc[num] || 0) + 1;
return acc;
}, {});
}
console.log(countOccurrences([1, 2, 2, 3, 3, 3]));
// { 1: 1, 2: 2, 3: 3 }
// Find numbers appearing exactly once
function findUnique(arr) {
const counts = countOccurrences(arr);
return Object.keys(counts)
.filter(key => counts[key] === 1)
.map(Number);
}
console.log(findUnique([1, 2, 2, 3, 4, 4, 5])); // [1, 3, 5]
// Unique objects by property
const users = [
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 1, name: 'John Doe' },
{ id: 3, name: 'Bob' }
];
function uniqueByProperty(arr, prop) {
const seen = new Map();
return arr.filter(item => {
if (seen.has(item[prop])) {
return false;
}
seen.set(item[prop], true);
return true;
});
}
console.log(uniqueByProperty(users, 'id'));
// [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }, { id: 3, name: 'Bob' }]
// Performance comparison
const largeArray = Array.from({ length: 100000 }, () =>
Math.floor(Math.random() * 10000)
);
console.time('Set method');
[...new Set(largeArray)];
console.timeEnd('Set method');
console.time('Filter method');
largeArray.filter((n, i) => largeArray.indexOf(n) === i);
console.timeEnd('Filter method');
console.time('Map method');
const map = new Map();
largeArray.forEach(n => map.set(n, true));
Array.from(map.keys());
console.timeEnd('Map method');
// Result: Set is fastest, followed by Map, then filterKey Points
- Set is the best method: simple, fast O(n), and readable
- filter + indexOf is intuitive but slow O(n²) for large arrays
- Map/Object hash is fast O(n) but uses extra memory
- Nested loops are slowest - avoid for production code
- Choose method based on: array size, readability needs, memory constraints
- Set preserves insertion order (ES6+)
- For objects, use Map with custom key extraction