Dynamic Programming: return all matched data in JavaScript

Dynamic programming in JavaScript can be used to efficiently search and retrieve data from nested structures. This article demonstrates how to search for all matching cities in a complex JSON object containing country and province information.

The Data Structure

We have a nested JSON object with countries, provinces, and cities:

const countryInfo = {
    country: [{
        name: "Bangladesh",
        province: [{
            name:"Dhaka",
            city: [{
                name:"Tangail",
                lat: '11'
            }, {
                name:"Jamalpur",
                lat: '12'
            }]
        }, {
            name: "Khulna",
            city: [{
                name:"Jossore",
                lat: '22'
            }, {
                name:"Tangail",
                lat: '23'
            }]
        }, {
            name: "Rajshahi",
            city: [{
                name:"Pabna",
                lat: '33'
            }, {
                name:"Rangpur",
                lat: '33'
            }]
        }]
    },{
        name: "India",
        province: [{
            name:"West Bengal",
            city: [{
                name:"Calcutta",
                lat: '111'
            }, {
                name:"Tangail",
                lat: '112'
            }]
        }, {
            name: "Uttar Pradesh",
            city: [{
                name:"Agra",
                lat: '122'
            }, {
                name:"Tajmahal",
                lat: '123'
            }]
        }, {
            name: "Rajasthan",
            city: [{
                name:"Kanpur",
                lat: '131'
            }, {
                name:"Jaypur",
                lat: '132'
            }]
        }]
    }]
};

console.log("Data structure loaded successfully");
Data structure loaded successfully

The Search Function

Our function uses dynamic programming principles to flatten the nested structure and then filter for matching cities:

const searchForCity = (obj, query) => {
    // First, extract all cities using reduce to flatten the structure
    const cities = obj.country.reduce((acc, val) => {
        val.province.forEach(el => {
            el.city.forEach(elm => {
                acc.push(elm);
            });
        });
        return acc;
    }, []);
    
    // Filter cities that match the query
    const res = cities.filter(el => {
        return el.name === query;
    });
    
    return res;
};

// Test the function
console.log("Searching for 'Tangail':");
console.log(searchForCity(countryInfo, 'Tangail'));
Searching for 'Tangail':
[
    { name: 'Tangail', lat: '11' },
    { name: 'Tangail', lat: '23' },
    { name: 'Tangail', lat: '112' }
]

How It Works

The function operates in two phases:

  1. Flattening Phase: Uses reduce() to traverse all countries and provinces, collecting all city objects into a single array
  2. Filtering Phase: Uses filter() to return only cities matching the search query

Alternative Implementation with Better Performance

For better performance, we can avoid creating the intermediate array and directly filter while traversing:

const searchForCityOptimized = (obj, query) => {
    const results = [];
    
    obj.country.forEach(country => {
        country.province.forEach(province => {
            province.city.forEach(city => {
                if (city.name === query) {
                    results.push(city);
                }
            });
        });
    });
    
    return results;
};

// Test optimized version
console.log("Optimized search for 'Tangail':");
console.log(searchForCityOptimized(countryInfo, 'Tangail'));
Optimized search for 'Tangail':
[
    { name: 'Tangail', lat: '11' },
    { name: 'Tangail', lat: '23' },
    { name: 'Tangail', lat: '112' }
]

Case-Insensitive Search

To make the search more flexible, we can implement case-insensitive matching:

const searchForCityInsensitive = (obj, query) => {
    const results = [];
    const lowerQuery = query.toLowerCase();
    
    obj.country.forEach(country => {
        country.province.forEach(province => {
            province.city.forEach(city => {
                if (city.name.toLowerCase() === lowerQuery) {
                    results.push(city);
                }
            });
        });
    });
    
    return results;
};

// Test case-insensitive search
console.log("Case-insensitive search for 'tangail':");
console.log(searchForCityInsensitive(countryInfo, 'tangail'));
Case-insensitive search for 'tangail':
[
    { name: 'Tangail', lat: '11' },
    { name: 'Tangail', lat: '23' },
    { name: 'Tangail', lat: '112' }
]

Comparison of Methods

Method Memory Usage Performance Features
Original (reduce + filter) Higher Good Functional approach
Optimized (direct iteration) Lower Better Memory efficient
Case-insensitive Lower Better Flexible matching

Conclusion

Dynamic programming techniques in JavaScript help efficiently search nested data structures. The key is to flatten or traverse the structure systematically and apply filtering logic to return all matching results.

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

367 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements