오늘은 마지막 확인문제중 반복문을 이용하여 한개의 객체에 *로 이루어진 다이아몬드 모양을 만드는 문제를
1시간을 고민하다 정답을 보게 되었다.
피라미드형식으로 쌓는것에는 성공하였지만 도저히 역피라미드 모양을 만드는게 안되어 확인했었다.
정답을 보니 허탈했고, 왜 거기까지는 내가 생각하지 못했나를 한탄하게 되었다.
!true = false
!false = true
배열
배열은 여러 자료를 묶어 한번에 선언해 다룰 수 있게 만드는 자료형이다.
[ ] 대괄호를 사용하고, 내부에서 쉼표(,)로 분리한다. 내부에 있는 값들을 요소라 칭한다.
어제 틀렸던 문제를 여기서 확인 할 수 있었다.
숫자로 이루어진 변수를 배열에 관한 코드로 풀려다보니 해결이 안되었었는데, 배열을 공부해보니 완벽히 틀렸었다는걸 알게 되었다.
특히나 배열의 요소 개수를 확인하는 속성이던 length에 관해 알게되었다.
.length
const fruits = ['배','사과','키위','바나나']
fruits.length
fruits[fruits.length-1]
배열의 뒷부분에 요소를 추가하는 법 .push()
const fruits = ['배','사과','키위','바나나']
fruits.push('감')
fruits
배열의 뒷부분에 요소를 추가하는 법 .length()
배열은 인덱스형식으로 저장되어 처음 저장되는 요소가 0번으로 시작된다.
const fruits = ['배','사과','키위','바나나']
fruits[fruits.length]='감'
그런데 length는 요소의 갯수를 세주는 것이어서 위와같이 fruits.length인 4에 '감'을 추가하게되면
5번째 자리에 4번인덱스로 '감'이 추가되고 총 length가 5인 배열로 바뀌게 된다.
배열 요소 제거하기 .splice()
1) 인덱스 기반으로 제거
splice는 접합 이라는 뜻으로 특정 부분을 잘라서 나머지 인덱스끼리 붙이는 뜻으로 이해하면 쉽다.
splice(인덱스, 제거할 요소의 개수)로 사용한다.
사용되는 예로는
const fruits = ['배','사과','키위','바나나']
fruits.splice(2,1)
fruits
위와 같이 사용했을 시 키위만 제거되어 결과는 ['배', '사과', '바나나'] 로 표시된다.
2) 값으로 요소 제거
//예시시작
const 인덱스 = 배열.indexof(요소)
배열.splice(인덱스,1)
//예시 끝
const fruits = ['배','사과','키위','바나나']
const index = fruits.indexOf('바나나')
fruits.splice(index,1)
위와 같이 사용했을 시 마지막의 바나나 1개만 배열에서 삭제된다.
배열의 특정 위치에 요소 추가하기
//예시시작
배열.splice(인덱스,0,요소)
//예시 끝
const itemsD = ['사과','귤','바나나','오렌지']
items.splice(1,0,'양파')
위와 같이 메소드 2번 자리에 0을 입력하면 1번 메소드가 가리키는 위치의 인덱스에 3번메소드의 값이 입력된다.
비파괴적 처리
비파괴적 처리는 처리 후에 원본 내용이 변경되지 않는 것을 의미한다.
const a= '안녕'
const b= '하세요'
const c= a+b
c의 값은 '안녕하세요'로 출력되나 a와 b에 입력된 값이 영향을 받지 않으므로 이는 비파괴적 처리이다.
파괴적 처리
파괴적 처리란 앞에서 보았던 push로
const fruits = ['배','사과','키위','바나나']
fruits.push('감')
배 사과 키위 바나나로 이루어진 원래의 fruits에 새로운 '감'이 입력되면서 원형을 변형시키므로
이는 파괴적 처리로 분류된다.
과거 메모리가 부족하던 시기에는 메모리 절약을 위해 파괴적 처리로 했으니 이는 원본이 사라질 위험이 있었다.
최근들어 메모리가 풍족해지고 이에 따라 대부분 자료보호를 위해 비파괴적 처리로 하고있다.
이 둘은 시험과 면접때 자주 구분하라 해본다니 꼭 어떤 처리인지 구분 할 수 있어야 한다.
반복문
for in 반복문
for in 반복문은 배열과 함께 사용 할 수 있으며, 배열 요소 하나하나 꺼내어 특정 문장을 실행 할 때 사용한다.
//예시시작
const todos = ['우유 구매','업무 메일 확인하기','필라테스 수업']
//예시 끝
for (const i in todos) {
console.log(`${i}번째 할 일: ${todos[i]}`)
}
for of 반복문
for in 반복문은 반복 변수가 인덱스에 들어가서 반복문 내부에서 사용하려면 fruits[i]같은 형태로 사용하며, 안정성을 위해 몇가지 코드를 추가한다. 그래서 등장한게 for of 반복문이고, 요소의 값을 반복 할 때 안정적으로 사용 할 수 있다.
//예시시작
for (const 반복변수 of 배열 또는 객체){
문장
}
//예시 끝
const todos = ['우유구매','업무 메일 확인하기','필라테스 수업']
for (const todo of todos) {
console.log(`오늘의 할 일: ${todo}`)
}
for 반복문
특정 횟수를 반복하고 싶을 때 사용한다.
다른 반복문들과 다르게 for문 안에 const가 아닌 let으로 선언한다.
//예시시작
for (let i=0; i<반복횟수; i++){
문장
}
//예시 끝
for (let i=0; i<5; i++){
console.log(`${i}번째 반복입니다.`)
//1부터 100까지 더하기
<script>
let output = 0
for (i=1; i<=100; i++){
output +=1
}
console.log(`1~100까지 숫자를 더하면 ${output}입니다.`)
</script>
for 반복문과 함께 배열 사용하기
//
<script>
const todos = ['우유구매','업무 메일 확인하기','필라테스 수업']
for (let i =0; i < todos.length; i++){
console.log(`${i}번째 할 일: ${todos[i]}`)
}
</script>
for 반복문으로 배열을 반대로 출력하기
// for 반복문은 빠른 속도로 많은 양을 반복 작업하기 때문에 사용범위가 넓다.
<script>
const todos = ['우유구매','업무 메일 확인하기','필라테스 수업']
for (let i = todos.length-1; i>=0; i--){
console.log(`${i}번째 할 일: ${todos[i]}`)
}
</script>
while 반복문
조건이 변하지 않으면 무한 실행되므로 조건을 거짓으로 만들 수 있어야한다.
조건에 단순히 true를 넣으면 무한반복되는 상황에 빠지게 된다.
//
<script>
let i = 0
while (confirm('계속 진행하시겠습니까?')) {
//사용자가 확인을 누르면 true가 되어 반복함
alert(`${i}번째 반복입니다.`)
i=i+1
}
</script>
while 반복문과 배열 함께 사용하기
//
<script>
let i = const array = [1,2,3,4,5]
while (i<array.length){
console.log(`${i} : ${array[i]}`)
i++
}
</script>
위처럼 횟수가 정해진 것은 for문을 통해 코드를 간결히 하는게 더 좋다.
while문은 '특정 시간동안 어떤 데이터를 받을 때 까지' / '배열에서 어떠한 요소가 제거 될 때까지'
두가지 같은 조건이 큰 비중이 있을 때 사용하는게 좋다.
break 키워드
switch나 while문을 벗어나게 해준다.
//
<script>
for (let i=0; true; i++){
alert(i+'번째 반복문입니다.')
//진행여부
const isContinue = confirm('계속하시겠습니까?')
if (!isContinue){
break
}
}
alert('프로그램 종료')
</script>
continue 키워드
반복문 안의 반복 작업을 멈추고 반복문의 처음으로 돌아가 다음 반복 작업을 진행한다.
//
<script>
let output = 0
for (let i=1; i<=10; i++){
//i가 홀수라면 다음 명령을 건너뛰고 반복문으로 돌아간다. 따라서 짝수만 output에 더해지게 된다.
if (i%2 == 1){
continue
}
output+=1
}
alert(output)
</script>
틀린문제
for문을 이용하여 *로 다이아몬드 모양을 만들어라.
처음 작성했던 코드이다.
<script>
const size = 5
let output = ''
for (let i=1; i<10; i++){
if (i<=size){
for (let j=5; j>i; j--){
output+=' '
}
for (let k=0; k<2*i-1; k++){
output += '*'
}
output +='\n'
} else {
for (let j=5; j<i; j++){
output +=' '
}
for (let k=5; k<2*i; k++){
output += '*'
}
output += '\n'
}
}
console.log(output)
</script>
나름 잘 풀었다고 생각했다. output의 6번쨰 줄까지만해도 결과는 제대로 나왔다.
하지만 역삼각형 모양을 구현하는데 실패했다.
다음으로 정답이 나온 코드다.
<script>
const size = 5
let output = ''
for (let i=1; i<=size; i++){
for (let j=5; j>i; j--){
output+=' '
}
for (let k=0; k<2*i-1; k++){
output += '*'
}
output +='\n'
}
for (let i=size-1; i>0; i--){
for (let j=size; j>i; j--){
output +=' '
}
for (let k=0; k<2*i-1; k++){
output += '*'
}
output += '\n'
}
console.log(output)
</script>
굳이 사용할 필요가 없었던 if문을 제거하고 두가지 중첩반복문으로 바꾸었다.
방법자체도 문제였고, 변수설정부터 틀린것으로 보인다.
콘솔로그는 정답과 일치하게 나왔다.
세번째로 처음 작성하려했던 if문에 올바른 변수를 입력했을 때 이다.
<script>
const size = 5
let output = ''
for (let i=1; i<10; i++){
if (i<=size){
for (let j=5; j>i; j--){
output+=' '
}
for (let k=0; k<2*i-1; k++){
output += '*'
}
output +='\n'
} else {
for (let j=size; j>i; j--){
output +=' '
}
for (let k=0; k<2*i-1; k++){
output += '*'
}
output += '\n'
}
}
console.log(output)
</script>
마찬가지로 콘솔로그도 원하는 방향과 일치하지 않게 출력되었다.
솔직히 말하자면 답지를 보고 답안을 작성하면서도 이해가 안갔고, 30분을 혼자 고민해 보고서야
왜 이렇게 나오는지 알게 되었다.
나는 반복문으로서의 for은 이해했으나, 중첩 반복문의 작동방식에 오해를 가지고 있었다.
내부의 for문 안의 j와 k가 값이 유지된다고 생각했고, 그래서 *의 갯수가 틀리거나, 무한루프가 걸렸던 것이다.
i의 값이 4에서 3으로 3에서 2로 갈때마다 내부의 k와 j값은 다시 초기인 5와0이 되어야 하는데
나는 i의 값이 4일때 j는 5 k는0 / i의 값이 3일때 j는4 k는1 / i의 값이 2일때 j는3 k는2 / i의 값이 1일때 j는2 k는 3 / 이렇게 말이다.
기본기가 단단하지 않아 일어난 일이라고 생각하고, 아직 경험이 부족하고 중첩 반복문을 처음 접해본 것 때문이라고 생각한다.
앞으로 많은 for문을 접해보면서 더욱더 익숙해지고 다듬어 나가야 겠다고 생각을 하였다.
'1차 공부 > TIL' 카테고리의 다른 글
221118 til (0) | 2022.11.18 |
---|---|
221112 객체(6장) (0) | 2022.11.12 |
221111 함수 (5장) (2) | 2022.11.11 |
221108 조건문(3장) (0) | 2022.11.08 |
221107 자바스크립트 개요 및 자료와 변수(1~2장) (0) | 2022.11.07 |