List all duplicate values in a nested JavaScript object

When working with nested JavaScript objects, you may need to find duplicate values that appear at different levels of nesting. This tutorial shows how to recursively search through a nested object and identify all duplicate values.

Problem Statement

Consider a nested object containing pet information:

const pets = {
    owner1: 'Frank',
    owner2: 'Curly',
    owner3: 'Maurice',
    dogs: {
        terriers: {
            name1: 'Fido',
            name2: 'Woofy',
            name3: {
                goodDog: 'Frank',
                badDog: 'Judas',
            }
        },
        poodles: {
            name1: 'Curly',
            name2: 'Fido',
        },
    },
};

console.log(pets);
{
  owner1: 'Frank',
  owner2: 'Curly',
  owner3: 'Maurice',
  dogs: {
    terriers: { name1: 'Fido', name2: 'Woofy', name3: [Object] },
    poodles: { name1: 'Curly', name2: 'Fido' }
  }
}

We need to find values that appear multiple times across all levels: 'Frank', 'Curly', and 'Fido'.

Solution: Recursive Search Function

Here's a function that recursively traverses the object and tracks value occurrences:

const pets = {
    owner1: 'Frank',
    owner2: 'Curly',
    owner3: 'Maurice',
    dogs: {
        terriers: {
            name1: 'Fido',
            name2: 'Woofy',
            name3: {
                goodDog: 'Frank',
                badDog: 'Judas',
            }
        },
        poodles: {
            name1: 'Curly',
            name2: 'Fido',
        },
    },
};

const recursiveSearch = (obj, map = {}, res = []) => {
    Object.keys(obj).forEach(key => {
        if(typeof obj[key] === "object"){
            return recursiveSearch(obj[key], map, res);
        };
        map[obj[key]] = (map[obj[key]] || 0) + 1;
        if(map[obj[key]] === 2){
            res.push(obj[key]);
        }
    });
    return res;
};

console.log(recursiveSearch(pets));
[ 'Frank', 'Curly', 'Fido' ]

How It Works

The algorithm uses three key components:

  • map: Tracks how many times each value appears
  • res: Stores duplicate values (added when count reaches 2)
  • Recursion: Handles nested objects by calling itself

Step-by-Step Process

Let's trace through the execution with a simpler example:

const simpleObj = {
    a: 'hello',
    b: 'world',
    nested: {
        c: 'hello',
        d: 'test'
    }
};

const findDuplicates = (obj, map = {}, res = []) => {
    Object.keys(obj).forEach(key => {
        console.log(`Processing key: ${key}, value: ${obj[key]}`);
        
        if(typeof obj[key] === "object"){
            console.log(`Found nested object, recursing...`);
            return findDuplicates(obj[key], map, res);
        };
        
        map[obj[key]] = (map[obj[key]] || 0) + 1;
        console.log(`Value '${obj[key]}' count: ${map[obj[key]]}`);
        
        if(map[obj[key]] === 2){
            res.push(obj[key]);
            console.log(`Duplicate found: ${obj[key]}`);
        }
    });
    return res;
};

console.log("Final duplicates:", findDuplicates(simpleObj));
Processing key: a, value: hello
Value 'hello' count: 1
Processing key: b, value: world
Value 'world' count: 1
Processing key: nested, value: [object Object]
Found nested object, recursing...
Processing key: c, value: hello
Value 'hello' count: 2
Duplicate found: hello
Processing key: d, value: test
Value 'test' count: 1
Final duplicates: [ 'hello' ]

Alternative Implementation

Here's a cleaner version that separates concerns:

function findDuplicatesInObject(obj) {
    const valueCount = {};
    
    function traverse(current) {
        Object.values(current).forEach(value => {
            if (typeof value === 'object' && value !== null) {
                traverse(value);
            } else {
                valueCount[value] = (valueCount[value] || 0) + 1;
            }
        });
    }
    
    traverse(obj);
    
    return Object.keys(valueCount).filter(value => valueCount[value] > 1);
}

const pets = {
    owner1: 'Frank',
    owner2: 'Curly',
    owner3: 'Maurice',
    dogs: {
        terriers: {
            name1: 'Fido',
            name2: 'Woofy',
            name3: {
                goodDog: 'Frank',
                badDog: 'Judas',
            }
        },
        poodles: {
            name1: 'Curly',
            name2: 'Fido',
        },
    },
};

console.log(findDuplicatesInObject(pets));
[ 'Frank', 'Curly', 'Fido' ]

Conclusion

Finding duplicates in nested objects requires recursive traversal to visit all values at every level. The key is maintaining a count map and identifying when values appear more than once across the entire object structure.

Updated on: 2026-03-15T23:19:00+05:30

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements