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

JavaScript에서 서로 다른 두 배열을 하나로 결합하는 방법 – id 기준 데이터 병합

두 개의 배열이 있다고 가정해 보겠습니다. 첫 번째 배열에는 여러 이벤트의 예정된 날짜가 담겨 있고, 두 번째 배열에는 그 이벤트들의 이름이 담겨 있습니다.

const dates = [
    {
        id:"1",
        date:"2017-11-07"
    },
    {
        id:"1",
        date:"2017-11-08"
    },
    {
        id:"2",
        date:"2017-11-07"
    },
    {
        id:"2",
        date:"2017-11-08"
    }
];
const names = [
    {
        id:"1",
        name:"Pervies, Peter"
    },
    {
        id:"2",
        name:"Ming, Edmund"
    }
];

여기서 필요한 것은 이 두 배열을 입력으로 받아 id 속성을 기준으로 이벤트 이름과 그에 해당하는 날짜들을 하나로 묶어 주는 JavaScript 함수입니다.

따라서 위와 같은 배열이 주어졌을 때 최종 출력 결과는 다음 형태가 되어야 합니다.

const output = [
    {
        id:"1",
        name:"Pervies, Peter",
        details:[
            {date:"2017-11-07"},
            {date:"2017-11-08"}
        ]
    },
    {
        id:"2",
        name:"Ming, Edmund",
        details:[
            {date:"2017-11-07"},
            {date:"2017-11-08"}
        ]
    }
];

구현 예제

이를 구현한 전체 코드는 다음과 같습니다.

const combineArrays = (dates, names) => {
    const res = [];
    dates.forEach(el => {
        const bool = !res.some(item => {
            return item.id == el.id;
        });
        if(bool){
            let combined = {};
            combined.id = el.id;
            combined.details = combined.details || [];
            combined.details.push({
                "date": el.date
            });
            res.push(combined);
        }else{
            res.find(item => {
                return item.id === el.id;
            })
            .details.push({
                "date": el.date
            });
        };
    });
    res.forEach(el => {
        const bool = names.some(item => {
            return item.id === el.id;
        });
        if(bool){
            el.name = names.find(name => {
                return name.id === el.id;
            }).name;
        };
    });
    return res;
};
console.log(JSON.stringify(combineArrays(dates, names), undefined, 4));

출력 결과

콘솔에 출력되는 결과는 다음과 같습니다.

[
    {
        "id": "1",
        "details": [
            {
                "date": "2017-11-07"
            },
            {
                "date": "2017-11-08"
            }
        ],
        "name": "Pervies, Peter"
    },
    {
        "id": "2",
        "details": [
            {
                "date": "2017-11-07"
            },
            {
                "date": "2017-11-08"
            }
        ],
        "name": "Ming, Edmund"
    }
]

코드 동작 방식

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

  • 1단계 – 날짜 그룹화: dates 배열을 순회하면서 각 요소의 id가 결과 배열(res)에 이미 존재하는지 확인합니다. 존재하지 않으면 새로운 객체를 생성해 details 배열에 날짜를 추가하고, 이미 존재한다면 해당 객체의 details 배열에 날짜만 이어서 추가합니다.
  • 2단계 – 이름 매핑: 완성된 결과 배열을 다시 순회하면서 names 배열에서 같은 id를 가진 항목을 찾아 name 속성을 할당합니다.

더 간결한 대안: Map 활용하기

ES6 문법을 활용하면 위 로직을 더욱 간결하고 효율적으로 작성할 수 있습니다. 특히 데이터 양이 많을 때는 some, find 같은 배열 메서드를 반복 호출하는 것보다 Map을 사용하는 것이 성능 면에서 유리합니다.

const combineArrays = (dates, names) => {
    const map = new Map();
    dates.forEach(({ id, date }) => {
        if (!map.has(id)) {
            map.set(id, { id, details: [] });
        }
        map.get(id).details.push({ date });
    });
    return [...map.values()].map(item => ({
        ...item,
        name: names.find(n => n.id === item.id)?.name
    }));
};
console.log(JSON.stringify(combineArrays(dates, names), undefined, 4));

두 방법 모두 동일한 결과를 반환하지만, Map 기반 접근 방식은 키 조회 시간이 거의 일정(O(1))하기 때문에 대량의 데이터를 처리할 때 더 나은 선택입니다.