7단원 '배열'의 여덟 레슨에서 9문제를 내고, 1~6단원에서 3문제를 섞었습니다. 앞 단원 문제가 어느 레슨인지는 정답을 펼치면 보입니다. 출력을 쓰는 문제는 빈칸과 줄바꿈까지 종이에 끝까지 쓴 뒤 정답을 펼치세요. 줄 수를 알려 주지 않는 문제는 마지막 줄까지 다 씁니다. 배열을 다루는 코드는 이름표가 어느 배열에 붙는지, 바퀴마다 이름이 어느 값에 붙는지 적으며 따라가면 덜 틀립니다. 막히면 정답 앞의 힌트를 먼저 펼칩니다. 점수는 매기지 않습니다.
한 번에 다 풀 필요는 없습니다. 문제 1~10은 폰으로도 풀 수 있고(약 30~40분), 끝의 만들어 보기 둘은 컴퓨터에서 Node로 직접 돌려 봅니다. 이 단원을 건너뛰어도 되는지 보려면 문제 1 · 2 · 4 · 6 · 8 · 9 여섯을 먼저 풀어 보세요(약 15분). 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다. 힌트를 펴고 맞힌 문제나 짐작으로 고른 문제는 틀린 것으로 치고 그 레슨을 봅니다. 모두 맞으면 이 단원 레슨은 건너뛰고, 틀린 문제가 있으면 그 정답 끝의 레슨만 봅니다. 파이썬을 배웠다면 파이썬과 달라지는 곳이 이 여섯에 들어 있습니다(정답의 '파이썬에서는' 줄). 끝의 만들어 보기 둘은 골라서 풉니다.
끝의 두 문제는 프로그램을 직접 만들어 봅니다. 컴퓨터가 있으면 저장해 돌려 맞춰 보고, 폰으로만 본다면 문제에 적힌 값으로 내 코드를 한 줄씩 따라가 나와야 할 화면과 맞춰 봅니다. 실행 결과는 모두 Node 26으로 돌린 것입니다.
문제 1
모둠 명단에 친구를 한 명 더합니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const team = ['수아', '지호'];
const group = team;
group.push('민서');
console.log(team);
console.log(group.length);
힌트
2번 줄 뒤에 배열이 몇 개 있는지, team과 group이 각각 어느 배열에 붙는지 그려 보세요.
정답
[ '수아', '지호', '민서' ]
3- 1번 줄: 배열
['수아', '지호']를 만들고, team이 그 배열에 붙습니다. - 2번 줄: group도 team이 가리키는 그 배열에 붙습니다. 배열은 하나이고 이름표만 둘입니다.
- 3번 줄: group이 가리키는 배열 끝에 '민서'를 더합니다. team도 같은 배열을 가리키니 team으로 보아도 바뀌어 있습니다.
- 4~5번 줄: team을 찍으면
[ '수아', '지호', '민서' ]이고, group의 길이는 3입니다.
흔한 오답은 첫 줄을 [ '수아', '지호' ]로 쓰는 것입니다. 2번 줄에서 배열이 한 벌 복사되어 group 쪽만 바뀐다고 본 것입니다(복사된다는 생각). =는 배열을 복사하지 않고 같은 배열에 이름표를 하나 더 붙입니다(규칙 3). 따로 바꿀 사본이 필요하면 [...team]처럼 펼쳐 새 배열을 만듭니다.
다시 볼 레슨: 배열과 이름 둘
문제 2
메뉴 배열과 그 사본에 메뉴를 더합니다. 이 코드를 실행하면 어떻게 될까요? 알맞은 것을 고르세요.
const menu = ['라테', '모카'];
const copy = [...menu];
const n = menu.push('유자차');
console.log(n, copy.length);
copy.append('스콘');
console.log(menu);
- ①
3 2와[ '라테', '모카', '유자차' ]를 찍고 끝난다 - ② 아무것도 찍지 않고 3번 줄에서
TypeError로 멈춘다 - ③
3 2를 찍은 뒤 5번 줄에서TypeError로 멈춘다 - ④
[ '라테', '모카', '유자차' ] 2를 찍은 뒤 5번 줄에서TypeError로 멈춘다
힌트
2번 줄의 copy와 3번 줄의 n이 각각 무엇에 붙는지 적고, 5번 줄까지 한 줄씩 따라가 보세요.
정답
③ — 실행 결과는 이렇습니다.
3 2main.js:5copy.append('스콘'); ^ TypeError: copy.append is not a function at main.js:5:6- 2번 줄:
[...menu]는 menu의 칸 값을 펼쳐 새 배열을 만듭니다. copy는 menu와 다른 배열에 붙습니다. - 3번 줄:
push는 menu 끝에 '유자차'를 더하고 늘어난 길이 3을 돌려줍니다. n은 배열이 아니라 수 3에 붙습니다. menu를const로 만들었어도 배열 안은 바꿀 수 있습니다. - 4번 줄: copy는 따로인 배열이라 길이가 그대로 2입니다.
3 2를 찍습니다. - 5번 줄: 자바스크립트 배열에는
append가 없어copy.append는undefined입니다. 함수가 아닌 것을 부르려다TypeError로 멈추고, 6번 줄은 실행되지 않습니다.3 2가 먼저 찍히고 결과에at main.js:5:6줄이 있는 것이 실행 중 오류라는 표시입니다. - ① 배열 끝에 더하는 메서드가
append라고 본 것입니다. 끝에 더하는 것은push입니다. - ②
const로 만든 배열은 바꿀 수 없다고 본 것입니다(const는 얼린다는 생각).const로 만든 배열에도push로 칸을 더할 수 있습니다. - ④
push가 값을 더한 배열을 돌려준다고 본 것입니다.push는 새 길이를 돌려줍니다.
파이썬에서는 copy.append('스콘')으로 리스트 끝에 더합니다 — 자바스크립트 배열에는 append가 없어 TypeError가 나고, 끝에 더할 때는 push를 씁니다.
다시 볼 레슨: 배열 바꾸기와 복사 · 배열과 이름 둘
문제 3
장바구니 배열의 길이로 '몇 개' 글자를 만듭니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const cart = ['쌀', '김'];
let n = cart.length;
const label = `${n}개`;
cart.push('콩');
n = cart.length;
console.log(label);
console.log(n);
힌트
3번 줄이 실행되는 그때 n이 어느 값에 붙어 있는지, 5번 줄이 다시 붙이는 이름이 무엇인지 보세요.
정답
2개
3- 2번 줄: 그때 cart의 길이 2를 계산해 n이 2에 붙습니다.
- 3번 줄: 템플릿 문자열을 이 줄에서 한 번 계산해 만든 글자
'2개'에 label이 붙습니다. - 4~5번 줄: cart 끝에 '콩'을 더해 길이가 3이 되고, n은 3에 다시 붙습니다. label은 이미 만든 글자
'2개'에 그대로 붙어 있습니다. - 6~7번 줄:
2개와3을 찍습니다.
흔한 오답은 첫 줄을 3개로 쓰는 것입니다. 3번 줄에 식 ${n}개가 저장되어 찍을 때 다시 계산된다고 본 것입니다(식이 저장된다는 생각). =는 오른쪽을 그 줄에서 한 번 계산해 값 하나를 만들고, 왼쪽 이름을 그 값에 붙입니다(규칙 2).
다시 볼 레슨: 변수: let으로 이름 붙이기 · 템플릿 문자열로 출력 꾸미기
문제 4
주문마다 넣은 샷 수를 두 반복으로 더해 봅니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const shots = [2, 4, 1];
let a = 0;
let b = 0;
for (const shot of shots) {
a = a + shot;
}
for (const shot in shots) {
b = b + shot;
}
console.log(a);
console.log(b);
힌트
4번 줄의 of와 7번 줄의 in이 shot에 각각 무엇을 꺼내 주는지 비교해 보세요.
힌트 둘
for...in은 칸의 값이 아니라 자리 번호를 꺼내고, 그 번호는 글자 '0' · '1' · '2'입니다. 수와 글자를 +로 더하면 어떻게 되는지 떠올려 보세요.
정답
7
0012- 4~6번 줄:
for...of는 shot을 칸의 값 2, 4, 1에 차례로 붙입니다. a는 2, 6, 7에 차례로 다시 붙습니다. - 7~9번 줄:
for...in은 칸의 값 대신 자리 번호를 글자로 꺼내, shot이'0','1','2'에 차례로 붙습니다. - 8번 줄: 첫 바퀴의
0 + '0'은 수와 글자라 이어 붙이기가 되어'00'이고, 다음 바퀴부터'001','0012'가 됩니다. - 10~11번 줄:
7과0012를 찍습니다.
흔한 오답은 둘째 줄을 7이나 3으로 쓰는 것입니다. 7은 for...in도 칸의 값을 꺼낸다고 본 것이고, 3은 자리 번호를 꺼내는 것은 맞혔지만 그 번호가 수라고 본 것입니다. 배열의 값을 돌 때는 for...of를 씁니다.
파이썬에서는 for shot in shots:가 리스트의 값을 꺼냅니다 — 자바스크립트에서 값을 꺼내는 것은 for...of이고, for...in은 자리 번호를 글자로 꺼냅니다.
다시 볼 레슨: for...of로 배열 돌기
문제 5
달리기 기록 셋(초)을 모두 더합니다. 무엇이 찍힐까요? 마지막 줄까지 글자 그대로 쓰세요. 오류로 멈추면 찍힌 줄 다음에 오류 메시지의 …Error: 줄만 써도 됩니다.
const times = [62, 58, 60];
const n = times.length;
let total = 0;
for (let i = 0; i <= n; i++) {
total = total + times[i];
}
console.log(times[n]);
console.log(total);
힌트
4번 줄의 끝 조건 i <= n에서 i가 마지막에 몇까지 가는지, 그때 times[i]가 무엇인지 보세요.
정답
모두 두 줄입니다.
undefined
NaN- 2번 줄: n은 칸 수 3에 붙습니다. 자리 번호는 0부터라 마지막 칸은
times[2]입니다. - 4~6번 줄: 끝 조건이
i <= n이라 i가 0, 1, 2에 이어 3일 때도 한 번 더 돕니다. total은 62, 120, 180에 차례로 붙은 뒤, 없는 칸times[3]의undefined를 더해NaN에 붙습니다. - 7번 줄:
times[3]처럼 없는 칸을 읽으면 오류 없이undefined입니다. - 8번 줄:
NaN을 찍습니다.
흔한 오답은 60과 180을 쓰거나, 5번 줄에서 오류로 멈춘다고 쓰는 것입니다. 첫 줄을 60으로 쓰면 칸 수 3도 자리 번호에 들어 times[3]이 마지막 칸이라고 본 것이고(끝도 든다는 생각), 둘째 줄을 180으로 쓰면 끝 조건 i <= n이 한 번 더 돌린 마지막 바퀴(i가 3일 때)를 놓친 것입니다. 오류로 멈춘다고 쓰면 없는 칸을 읽으면 바로 오류가 난다고 본 것입니다(없으면 오류라는 생각). 칸이 셋이면 자리 번호는 0, 1, 2이고, 셋을 다 돌 때는 i < n으로 씁니다.
파이썬에서는 없는 칸 times[3]을 읽으면 IndexError로 멈춥니다 — 자바스크립트는 오류 없이 undefined를 주고, 그 값을 수에 더하면 NaN이 됩니다.
문제 6
사흘 동안 날마다 팔린 잔 수입니다. 가장 많이 판 날의 잔 수를 찾고, 10잔이 안 된 날의 잔 수를 골라 담습니다. 무엇이 찍힐까요? 세 줄을 글자 그대로 쓰세요.
const sales = [18, 25, 7];
let most = sales[0];
const slow = [];
for (const sale of sales) {
if (sale > most) {
most = sale;
}
if (sale < 10) {
slow.push(sale);
}
}
console.log(most);
console.log(slow);
console.log(Math.max(sales));
힌트
4~11번 줄에서 sale이 붙는 값마다 most와 slow가 어떻게 바뀌는지 적고, 14번 줄의 Math.max 괄호 안에 무엇이 들어갔는지 보세요.
힌트 둘
Math.max는 견줄 값을 인자로 하나씩 받아 수로 바꿉니다. 배열 하나를 통째로 넘기면 무엇을 수로 바꾸게 되는지 떠올려 보세요.
정답
25
[ 7 ]
NaN- 2~3번 줄: 첫 값 18을 지금까지 가장 큰 값으로 두고, 고른 값을 담을 빈 배열을 만듭니다.
- 4~11번 줄: sale이 18, 25, 7에 차례로 붙습니다. 25일 때
25 > 18이 참이라 most가 25에 다시 붙고, 7일 때7 < 10이 참이라 slow에 7이 담깁니다. - 12~13번 줄:
25와[ 7 ]을 찍습니다. - 14번 줄:
Math.max는 견줄 값을 인자로 하나씩 받아 수로 바꿉니다. 칸이 여럿인 배열을 통째로 받으면 수가 되지 못해NaN을 돌려줍니다.
흔한 오답은 셋째 줄을 25로 쓰는 것입니다. Math.max에 배열을 그대로 줘도 가장 큰 칸 값을 돌려준다고 본 것입니다. 배열의 값으로 부를 때는 Math.max(...sales)처럼 펼쳐 칸 값을 하나씩 넘깁니다.
파이썬에서는 max(sales)처럼 리스트를 통째로 넘깁니다 — 자바스크립트 Math.max에 칸이 여럿인 배열을 통째로 넘기면 오류 없이 NaN이 나옵니다.
다시 볼 레슨: 가장 큰 값 찾기 · 거르기와 바꿔 담기
문제 7
같은 판매 잔 수에서 30잔이 넘은 날만 걸러 봅니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const sales = [18, 25, 7];
const busy = sales.filter(
(s) => s > 30,
);
if (busy) {
console.log('바쁜 날 있음');
} else {
console.log('바쁜 날 없음');
}
console.log(busy.length);
힌트
2~4번 줄의 filter가 맞는 값이 하나도 없을 때 무엇을 돌려주는지 보고, 그 값이 5번 줄의 조건 자리에서 참인지 거짓인지 보세요.
정답
바쁜 날 있음
0- 2~4번 줄: 30보다 큰 값이 없어도
filter는undefined가 아니라 빈 배열[]을 돌려주고, busy가 그 배열에 붙습니다. - 5번 줄: 빈 배열은 거짓 같은 값 여덟에 들지 않아 참 같은 값입니다. 조건이 참이라 6번 줄이
바쁜 날 있음을 찍습니다. - 10번 줄: 빈 배열의 길이
0을 찍습니다.
흔한 오답은 첫 줄을 바쁜 날 없음으로 쓰는 것입니다. 빈 배열이 거짓 같은 값이라고 본 것입니다. 걸러 낸 값이 있는지 물을 때는 busy.length > 0처럼 길이로 묻습니다.
파이썬에서는 빈 리스트가 거짓이라 if busy:가 거짓 쪽으로 갑니다 — 자바스크립트는 빈 배열도 참 같은 값이라 길이로 묻습니다.
다시 볼 레슨: 참 같은 값과 ?? · map·filter·find
문제 8
수행평가 점수에 5점씩 더한 뒤, 100점이 넘는 점수는 100점으로 쳐서 합계를 냅니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const scores = [70, 98, 80];
const up = scores.map(
(s) => s + 5,
);
const total = up.reduce(
(sum, s) => {
if (s > 100) {
return sum + 100;
}
return sum + s;
},
0,
);
console.log(up);
console.log(total);
힌트
2~4번 줄이 만든 up을 먼저 적고, 5~13번 줄은 부름마다 sum과 s가 무엇에 붙는지 표로 적어 보세요.
힌트 둘
8번 줄의 return은 그 부름의 함수만 끝냅니다. 함수가 돌려준 값은 다음 부름의 sum이 됩니다.
정답
[ 75, 103, 85 ]
260- 2~4번 줄:
map은 칸마다 함수를 불러 돌려받은 값으로 새 배열[75, 103, 85]를 만들고, up이 그 배열에 붙습니다. scores는 그대로입니다. - 5~13번 줄:
reduce는 sum을 시작 값 0으로 두고 칸마다 함수를 부릅니다. 함수가 돌려준 값이 다음 부름의 sum이 됩니다.
| 부름 | sum | s | 돌려준 값 |
|---|---|---|---|
| 첫째 | 0 | 75 | 75 |
| 둘째 | 75 | 103 | 175 |
| 셋째 | 175 | 85 | 260 |
둘째 부름에서 8번 줄의 return은 그 부름의 함수만 끝내고 75 + 100인 175를 돌려줍니다. reduce는 멈추지 않고 셋째 칸 85로 넘어가, total이 마지막에 돌려준 260에 붙습니다.
흔한 오답은 둘째 줄을 175로 쓰는 것입니다. 103에서 return을 만나면 reduce 전체가 끝난다고 본 것입니다(콜백 안 return이 바깥까지 끝낸다는 생각). 함수는 부를 때마다 새 칸이 생기고, return은 그 칸만 끝냅니다(규칙 5).
다시 볼 레슨: map·filter·find · reduce로 하나로 모으기
문제 9
메뉴 셋이 팔린 잔 수를 두 메서드로 정렬합니다. 무엇이 찍힐까요? 두 줄을 글자 그대로 쓰세요.
const sold = [48, 105, 9];
const ranked = sold.toSorted();
sold.sort(
(a, b) => a - b,
);
console.log(ranked);
console.log(sold);
힌트
2번 줄의 toSorted() 괄호 안을 보고, 3~5번 줄의 sort가 sold가 가리키는 배열에 무엇을 하는지 보세요.
힌트 둘
비교 함수가 없으면 값을 글자로 바꿔 글자 차례로 견줍니다. '105' · '48' · '9'는 첫 글자부터 견줍니다. sort는 돌려준 값을 받지 않아도 그 배열을 제자리에서 정렬합니다.
정답
[ 105, 48, 9 ]
[ 9, 48, 105 ]- 2번 줄:
toSorted()는 sold를 그대로 두고 정렬한 새 배열을 돌려줍니다. 비교 함수가 없어 값을 글자로 바꿔 견주는데, 첫 글자'1'이'4'보다,'4'가'9'보다 앞이라 105, 48, 9 차례입니다. - 3~5번 줄:
sort는 새 배열을 만들지 않고 sold가 가리키는 배열을 제자리에서 정렬합니다. 비교 함수(a, b) => a - b가 있어 작은 수부터 놓입니다. 돌려준 값을 받지 않아도 sold는 바뀌어 있습니다. - 6~7번 줄: ranked는 2번 줄에서 만든 따로인 배열이라
[ 105, 48, 9 ]그대로이고, sold는[ 9, 48, 105 ]입니다.
흔한 오답은 첫 줄을 [ 9, 48, 105 ]로 쓰거나, 둘째 줄을 [ 48, 105, 9 ]로 쓰는 것입니다. 앞의 것은 비교 함수 없이도 수의 크기로 정렬된다고 보았거나, toSorted도 sort처럼 sold를 정렬해 같은 배열을 돌려준다고 본 것이고, 뒤의 것은 sort도 toSorted처럼 새 배열을 만들고 sold는 그대로 둔다고 본 것입니다(복사된다는 생각).
파이썬에서는 sorted([48, 105, 9])가 수 차례 [9, 48, 105]를 줍니다 — 자바스크립트 toSorted()·sort()는 비교 함수가 없으면 값을 글자로 바꿔 견주니, 수를 정렬할 때는 (a, b) => a - b를 넘깁니다.
다시 볼 레슨: 정렬: sort와 toSorted
문제 10
할 일 목록에서 다 한 일 '숙제'를 지웁니다. [ '빨래', '청소' ] 한 줄이 찍혀야 하는데, 아래처럼 3번 줄에서 멈췄습니다. 몇 번 줄의 무엇을 고쳐야 할까요? 한 줄만 고쳐, 고친 줄을 쓰세요.
const todos = ['빨래', '숙제'];
todos.push('청소');
todos = todos.filter(
(t) => t !== '숙제',
);
console.log(todos);
main.js:3todos = todos.filter( ^ TypeError: Assignment to constant variable. at main.js:3:7힌트
같은 todos를 바꾸는 2번 줄의 push는 지나갔는데 3번 줄에서 멈췄습니다. 두 줄이 todos에 하는 일이 어떻게 다른지, 오류 메시지의 constant variable이 몇 번 줄의 무엇을 가리키는지 보세요.
정답
1번 줄의 const를 let으로 고쳐 let todos = ['빨래', '숙제'];로 씁니다.
let todos = ['빨래', '숙제'];
todos.push('청소');
todos = todos.filter(
(t) => t !== '숙제',
);
console.log(todos);[ '빨래', '청소' ]오류는 3번 줄에서 났지만 고칠 곳은 todos를 만든 1번 줄입니다. const는 배열을 얼리지 않고 이름표를 다시 붙이는 것만 막습니다. 그래서 2번 줄의 push처럼 배열 안을 바꾸는 일은 되고, 3번 줄처럼 todos를 filter가 만든 새 배열에 다시 붙이는 일은 TypeError로 멈춥니다. let으로 만들면 3번 줄에서 todos가 새 배열 ['빨래', '청소']에 다시 붙습니다(규칙 3).
const로 만든 배열은 아예 바꿀 수 없다고 보면 2번 줄의push부터 멈췄어야 합니다(const는 얼린다는 생각). 2번 줄이 지나간 것은const가 막는 것이 다시 붙이기뿐이기 때문입니다.- 흔한 오답은 3번 줄 앞의
todos =를 지워todos.filter(로 시작하게 고치는 것입니다. 멈추지는 않지만[ '빨래', '숙제', '청소' ]가 찍힙니다.filter가 todos의 칸에서 '숙제'를 지운다고 본 것입니다.filter는 원래 배열을 그대로 두고 새 배열을 돌려주므로, 목록을 바꾸려면 그 새 배열에 이름을 다시 붙여야 합니다. - 3번 줄을
const left = todos.filter(로, 6번 줄을console.log(left);로 고쳐도 같은 줄이 찍히지만 두 줄을 고칩니다. 한 줄로 고치려면 다시 붙이기를 막은 1번 줄의const를 고칩니다. - 3번 줄을
const todos = todos.filter(로 고치면 이미 있는 이름을 또 만들려 해SyntaxError가 나고, 아무것도 찍지 못합니다. - 1번 줄을
var로 바꿔도 같은 줄이 찍히지만, 이 과목은var를 쓰지 않습니다(변수: let으로 이름 붙이기).
다시 볼 레슨: 배열과 이름 둘 · map·filter·find · 이름표 다시 붙이기와 const
문제 11 (만들어 보기)
이 단원의 작은 완성품인 '4000원 넘는 메뉴만 골라 합계'를 만들어 봅니다. 주문한 메뉴의 가격 배열 prices에서 4000원보다 비싼 값만 골라 picked에 담고(4000원은 들지 않습니다), 고른 값의 합계를 total에 구합니다. 뼈대의 마지막 줄 console.log(picked, total);이 이렇게 찍어야 합니다.
[ 4500, 5200 ] 9700
prices의 세 값을 900, 3000, 4000으로 바꾸면 이렇게 나와야 합니다.
[] 0
아래 뼈대에서 1~5번 줄과 마지막 줄은 그대로 두고, 주석 둘 아래를 채우세요. 다 쓰면 둘째 시험 값으로도 따라가 봅니다.
const prices = [
4500,
900,
5200,
];
// 1. 4000원 넘는 값만 거르기
// 2. 거른 값을 하나로 모으기
console.log(picked, total);
힌트
1번 주석 아래는 거르기라 filter, 2번 주석 아래는 하나로 모으기라 reduce를 씁니다. 빈 배열과 for...of로 써도 됩니다.
정답
모범 답입니다.
const prices = [
4500,
900,
5200,
];
// 1. 4000원 넘는 값만 거르기
const picked = prices.filter(
(p) => p > 4000,
);
// 2. 거른 값을 하나로 모으기
const total = picked.reduce(
(sum, p) => sum + p,
0,
);
console.log(picked, total);[ 4500, 5200 ] 9700prices를 900, 3000, 4000으로 바꾸면 p > 4000이 참인 값이 없어 picked가 빈 배열 []에 붙습니다. reduce는 함수를 한 번도 부르지 않고 시작 값 0을 돌려주니 [] 0이 찍힙니다.
- 다르게 써도 되는 곳:
const picked = [];를 만들고for...of로 돌며 4000보다 큰 값을push한 뒤,let total = 0;에 하나씩 더해도 됩니다. 함수의 매개변수 이름은price처럼 달라도 됩니다. - 찍은 화면이 위와 같고 둘째 시험 값에서도
[] 0이 나오면 맞습니다. - 흔한 오답:
- 조건을
p >= 4000으로 쓰면 둘째 시험 값에서[ 4000 ] 4000이 찍힙니다. 처음 시험 값에는 4000이 없어 드러나지 않으니 둘째 시험 값으로 봅니다. reduce의 시작 값0을 빼면 처음 시험 값은 맞지만, 둘째 시험 값에서는 빈 배열을 시작 값 없이 모으려다TypeError로 멈춥니다.- 함수 몸을
(p) => { p > 4000; }처럼 중괄호로 감싸고return을 빠뜨리면 함수가 늘undefined를 돌려줘, 처음 시험 값에서도[] 0이 찍힙니다.
- 조건을
다시 볼 레슨: 거르기와 바꿔 담기 · map·filter·find · reduce로 하나로 모으기
문제 12 (만들어 보기)
이번에는 빈 데서 씁니다. 사흘 동안 날마다 읽은 쪽수를 담은 배열 pages에서, 가장 많이 읽은 날이 며칠째인지와 그날 읽은 쪽수를 빈칸 하나로 이어 한 줄로 찍습니다. 날은 1일째부터 세고, 가장 많이 읽은 날이 여럿이면 앞의 날을 찍습니다. 이렇게 나와야 합니다.
2 41
1번 줄의 pages를 [30, 12, 30]으로 바꾸면 이렇게 나와야 합니다.
1 30
아래 칸의 1번 줄은 그대로 두고, 그 아래를 씁니다.
const pages = [24, 41, 17];
힌트
하위 목표 셋으로 나눠 씁니다 — 1. 첫 값을 최고로(쪽수와 그날이 며칠째인지 함께) · 2. 하나씩 꺼내 견주어 바꾸기(몇 번째 값인지 세면서) · 3. 끝나고 쓰기.
정답
모범 답입니다.
const pages = [24, 41, 17];
// 1. 첫 값을 최고로
let best = pages[0];
let day = 1;
// 2. 하나씩 꺼내 견주어 바꾸기
let n = 0;
for (const page of pages) {
n = n + 1;
if (page > best) {
best = page;
day = n;
}
}
// 3. 끝나고 쓰기
console.log(day, best);2 41pages를 [30, 12, 30]으로 바꾸면 best가 첫 값 30, day가 1로 시작합니다. 셋째 값 30은 30 > 30이 거짓이라 바꾸지 않아 1 30이 찍힙니다.
- 다르게 써도 되는 곳: n을 따로 세지 않고
for로 자리 번호 i를 돌며pages[i] > best일 때day = i + 1;로 써도 됩니다. 이름은most·when처럼 달라도 됩니다. best를 0으로 시작해도 쪽수는 0보다 작지 않아 여기서는 같게 찍히지만, 값이 모두 0보다 작은 배열에서는 0이 끝까지 남아 틀리니 첫 값으로 시작합니다. - 찍은 화면이 위와 같고 둘째 시험 값에서도
1 30이 나오면 맞습니다. - 흔한 오답:
- 견주는 조건을
page >= best로 쓰면 같은 쪽수인 뒤의 날로 바뀌어 둘째 시험 값에서3 30이 찍힙니다. - 날을 자리 번호처럼 0부터 세면
1 41이 찍힙니다. 날은 1일째부터 셉니다. let best = pages[0];을 반복 안에 두면 best가 반복의 중괄호 안에서만 살아, 마지막 줄에서ReferenceError로 멈춥니다(규칙 4).
- 견주는 조건을
다시 볼 레슨: 가장 큰 값 찾기 · for...of로 배열 돌기
틀린 문제는 그 레슨으로 돌아가 모션 그림과 '자주 틀리는 곳'을 보고, 하루쯤 지난 뒤 그 문제만 다시 풀어 보세요. 그날 바로 다시 풀면 방금 본 정답이 기억나 맞힌 것인지 알기 어렵습니다.