Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript로 중첩된 JSON 객체에서 일치하는 모든 도시 데이터 검색하기

문제 소개

여러 국가와 그 하위의 주(province), 그리고 각 주에 속한 도시 정보를 계층 구조로 담고 있는 JSON 객체가 있다고 가정해 보겠습니다. 아래 예시 데이터에는 Bangladesh와 India 두 나라의 도시 정보가 포함되어 있습니다.

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

이제 이러한 객체와 검색 문자열을 인자로 받아, 검색어와 이름이 일치하는 모든 도시 객체를 배열로 반환하는 JavaScript 함수를 작성해 보겠습니다. 핵심은 같은 이름의 도시가 여러 나라, 여러 주에 중복해서 존재할 수 있다는 점입니다. 예를 들어 'Tangail'은 Bangladesh의 두 주와 India의 한 주에 걸쳐 등장하므로, 검색 시 세 곳 모두에서 찾아내야 합니다.

구현 코드

const searchForCity = (obj, query) => {
    const cities = obj.country.reduce((acc, val) => {
        val.province.forEach(el => {
            el.city.forEach(elm => {
                acc.push(elm);
            });
        });
        return acc;
    }, []);
    const res = cities.filter(el => {
        return el.name === query;
    });
    return res;
};
console.log(searchForCity(countryInfo, 'Tangail'));

코드 동작 원리

위 함수는 크게 두 단계로 동작합니다.

  1. 도시 목록 평탄화: reduce()로 country 배열을 순회하면서, 각 국가의 province 배열과 그 안의 city 배열을 중첩 forEach()로 끝까지 탐색해 모든 도시 객체를 하나의 배열(acc)에 모읍니다.
  2. 조건에 맞는 도시 필터링: 평탄화된 배열에 filter()를 적용해 name 속성이 검색어와 정확히 일치(===)하는 도시만 남긴 뒤 그 결과를 반환합니다.

대소문자 구분 없이 부분 일치 검색을 원한다면 마지막 비교 조건을 el.name.toLowerCase().includes(query.toLowerCase())로 변경하면 됩니다.

실행 결과

'Tangail'로 검색했을 때 콘솔 출력은 다음과 같습니다.

[
    { name: 'Tangail', lat: '11' },
    { name: 'Tangail', lat: '23' },
    { name: 'Tangail', lat: '112' }
]

같은 이름의 도시가 서로 다른 위도(lat) 값을 가진 채 여러 곳에 존재하기 때문에 세 개의 객체가 모두 반환됩니다. 이처럼 reduce()로 깊이 중첩된 데이터를 평탄화한 뒤 filter()로 조건을 적용하는 패턴은, 복잡한 JSON 구조에서 원하는 데이터를 유연하게 검색할 때 널리 활용되는 방식입니다.