-
Notifications
You must be signed in to change notification settings - Fork 0
MinJeong Hong edited this page Jan 9, 2026
·
1 revision
class Manager {
constructor() {
this.record = {}; // 빈 객체로 시작
this.data = []; // 빈 배열로 시작
}
}// reduce로 빈 객체부터 시작
const result = items.reduce((acc, item) => {
// ... 로직
return acc;
}, {});가장 자주 사용되는 패턴
// 배열 데이터를 키별로 그룹화
const record = {};
rawData.forEach(([key, value]) => {
if (!record[key]) {
// 키가 없으면 배열 생성
record[key] = [];
}
record[key].push(value); // 배열에 추가
});
// 예시: { '크루1': [데이터1, 데이터2], '크루2': [데이터3] }const target = records[index];
target.checkIn = [hour, min];
target.isAttendance = true;// 기존 객체에 속성 추가
const newData = { ...data, worker: '김철수' };
// 여러 속성 한번에 추가
const updated = { ...prev, checkIn: time, isAttendance: true };const products = { 콜라: 1000, 사이다: 1500 };
const names = Object.keys(products); // ['콜라', '사이다']const products = { 콜라: 1000, 사이다: 1500 };
Object.entries(products).forEach(([name, price]) => {
console.log(name, price);
});
// 객체를 배열로 변환
const entries = Object.entries(products);
// [['콜라', 1000], ['사이다', 1500]]// 배열 → 객체 변환
const result = items.reduce((acc, item) => {
acc[item.name] = item.value;
return acc;
}, {});
// 예시: reduce로 그룹화
const grouped = lines.reduce((acc, line) => {
const [name, value] = line.split(',');
if (!acc[name]) {
acc[name] = [];
}
acc[name].push(value);
return acc;
}, {});// 객체의 모든 값을 변환
const transformed = Object.entries(obj).reduce((acc, [key, value]) => {
acc[key] = process(value);
return acc;
}, {});
// 객체 필터링
const filtered = Object.entries(obj).reduce((acc, [key, value]) => {
if (condition(value)) {
acc[key] = value;
}
return acc;
}, {});const records = [
{ day: 5, checkIn: [10, 30] },
{ day: 6, checkIn: [9, 0] },
];
// 특정 조건의 객체 찾기
const target = records.find((record) => record.day === 5);
// 인덱스 찾기
const index = records.findIndex((record) => record.day === 5);const filtered = records.filter((record) => record.isAttendance);const names = records.map((record) => record.name);
const transformed = records.map((record) => ({
...record,
newProperty: value,
}));// 스프레드 연산자
const copy = { ...original };
// 이전 상태 저장용
const prev = { ...records[index] };// 배열 전체 복사
const newArray = [...oldArray];
// 객체 배열에서 특정 객체만 복사
const copiedItem = { ...array[index] };// 키가 있는지 확인
if (!obj[key]) {
obj[key] = []; // 없으면 초기화
}
// 또는
if (key in obj) {
// 키가 존재함
}// 안전한 접근
const records = this.record[nickname] || [];
// 중첩 객체 안전 접근
const value = obj?.level1?.level2 ?? 'default';// 객체 배열을 순회하며 집계
const total = items.reduce((sum, item) => {
return sum + item.price * item.quantity;
}, 0);
// 복잡한 집계 객체 생성
const summary = items.reduce(
(acc, item) => {
if (item.type === 'promotion') {
acc.promotionCount += item.quantity;
} else {
acc.regularCount += item.quantity;
}
acc.total += item.quantity;
return acc;
},
{ promotionCount: 0, regularCount: 0, total: 0 }
);// 객체의 모든 값 합산
const total = Object.entries(obj).reduce((sum, [key, value]) => {
return sum + value;
}, 0);
// 예시: 등수별 당첨 횟수 계산
const tally = { 1: 0, 2: 0, 3: 0 };
const totalPrize = Object.entries(tally).reduce((total, [rank, count]) => {
return total + PRICE_BY_RANK[rank] * count;
}, 0);// 가장 많이 사용!
const data = [
['크루1', '2024-12-01', '10:00'],
['크루2', '2024-12-01', '09:30'],
['크루1', '2024-12-02', '08:00'],
];
const grouped = {};
data.forEach(([nickname, date, time]) => {
if (!grouped[nickname]) {
grouped[nickname] = [];
}
grouped[nickname].push({ date, time });
});
// 결과: { '크루1': [{date, time}, ...], '크루2': [...] }// 객체의 값들을 배열로 변환
const crews = Object.keys(this.record); // ['크루1', '크루2']
// 객체를 배열로 변환하여 순회
Object.entries(this.record).forEach(([nickname, records]) => {
// 처리 로직
});// 날짜를 키로 사용하는 인덱스 생성
const recordsByDay = {};
records.forEach((record) => {
recordsByDay[record.day] = record;
});
// 빠른 조회
const day5Record = recordsByDay[5];✅ 객체에 데이터 추가할 때
- 키가 없으면 먼저 초기화:
if (!obj[key]) obj[key] = [] - 배열이면
push, 단일 값이면 직접 할당
✅ 객체 순회할 때
- 키만 필요:
Object.keys() - 키와 값 모두:
Object.entries() - 값만 필요:
Object.values()
✅ 객체 변환할 때
-
reduce로 새 객체 생성 -
Object.entries().reduce()패턴 기억하기
✅ 안전하게 접근할 때
-
obj[key] || []기본값 사용 -
if (!obj[key])존재 확인
✅ 복사가 필요할 때
- 스프레드 연산자:
{ ...obj } - 이전 상태 저장:
const prev = { ...current }
❌ 객체 초기화 안 하고 바로 push
// 잘못된 예
record[nickname].push(item); // undefined에 push 불가
// 올바른 예
if (!record[nickname]) {
record[nickname] = [];
}
record[nickname].push(item);❌ 원본 객체 직접 수정
// 주의: 원본이 변경됨
const target = records[index];
target.property = newValue; // records도 변경됨
// 필요시 복사 후 수정
const copy = { ...records[index] };
copy.property = newValue;여러 번 같은 키에 값을 추가/누적해야 할 때
// ✅ 검사 후 초기화 (누적식)
const grouped = {};
data.forEach(([name, value]) => {
if (!grouped[name]) {
// 키가 없으면 초기화
grouped[name] = [];
}
grouped[name].push(value); // 계속 추가
});
// 예시: 같은 이름의 데이터가 여러 번 나올 수 있음
// 입력: [['크루1', '데이터1'], ['크루2', '데이터2'], ['크루1', '데이터3']]
// 결과: { '크루1': ['데이터1', '데이터3'], '크루2': ['데이터2'] }왜 검사가 필요한가?
- 같은 키가 여러 번 나타날 수 있음
- 배열이나 값이 누적되어야 함
- 첫 번째 등장 시 초기화 필요
같은 키에 한 번만 값을 넣거나, 덮어써도 되는 경우
// ✅ 바로 넣기 (덮어쓰기 방식)
const mapped = {};
data.forEach(([id, name]) => {
mapped[id] = name; // 바로 할당, 이미 있으면 덮어씀
});
// 또는 reduce에서도
const result = items.reduce((acc, item) => {
acc[item.id] = item.value; // 검사 없이 바로 할당
return acc;
}, {});
// 예시: ID는 유일하므로 덮어쓸 일 없음
// 입력: [[1, '크루1'], [2, '크루2']]
// 결과: { 1: '크루1', 2: '크루2' }왜 검사가 불필요한가?
- 각 키가 한 번만 나타남 (유일한 키)
- 덮어써도 되는 경우
- 배열이 아닌 단일 값 할당
// 출석 기록: 같은 크루가 여러 날 출석
const attendance = [
['크루1', '2024-12-01'],
['크루2', '2024-12-01'],
['크루1', '2024-12-02'], // 크루1이 또 나옴!
['크루1', '2024-12-03'], // 크루1이 또 나옴!
];
const record = {};
attendance.forEach(([crew, date]) => {
if (!record[crew]) {
// ✅ 검사 필수!
record[crew] = [];
}
record[crew].push(date);
});
// 결과: { '크루1': ['2024-12-01', '2024-12-02', '2024-12-03'], '크루2': ['2024-12-01'] }// 상품 정보: 각 상품명은 한 번만 나옴
const products = [
['콜라', 1000],
['사이다', 1500],
['콜라', 1000], // 같은 상품이 다시 나와도 덮어써도 됨
];
const priceMap = {};
products.forEach(([name, price]) => {
priceMap[name] = price; // ✅ 검사 불필요, 바로 할당
});
// 결과: { '콜라': 1000, '사이다': 1500 }
// 마지막 값으로 덮어씀// 날짜별 정보: 각 날짜는 한 번만 나타남
const dates = [
{ day: 1, weekday: '월' },
{ day: 2, weekday: '화' },
{ day: 3, weekday: '수' },
];
const byDay = {};
dates.forEach((date) => {
byDay[date.day] = date; // ✅ 검사 불필요, 객체 바로 할당
});
// 결과: { 1: {day: 1, weekday: '월'}, 2: {...}, 3: {...} }- ✅ 같은 키가 여러 번 나타날 수 있음
- ✅ 배열에 값을 계속 추가해야 함 (
push) - ✅ 값이 누적되어야 함 (
+=,push) - ✅ 키별로 목록을 만들어야 함
- ✅ 각 키가 한 번만 나타남 (유일성 보장)
- ✅ 단일 값만 할당하면 됨
- ✅ 덮어써도 되는 경우
- ✅ 맵핑/변환 목적 (1:1 관계)
// 패턴 A: 누적식 (검사 + push)
if (!acc[key]) {
acc[key] = [];
}
acc[key].push(value);
// 패턴 B: 누적식 (검사 + 초기값)
if (!acc[key]) {
acc[key] = 0;
}
acc[key] += value;
// 패턴 C: 덮어쓰기 (바로 할당)
acc[key] = value;
// 패턴 D: 덮어쓰기 (객체 할당)
acc[key] = { ...item };기억하자:
- 배열(
push)이나 누적(+=) → 검사 필요 ✅ - 단일 할당(
=) → 검사 불필요 ❌