React

with JavaScripts Study Days 5-7

When to use
2021/05/05
Asset Type
List
File Type
Property
create time
2021/12/26 10:48

210502 일요일 5일차

# 3~4일차 복습

배열의 처음에 요소를 추가할 때 변형자 함수가 없다면 배열에 있던 기존 모든 요소를 한 칸씩 뒤로 이동시킨 다음 새 데이터를 추가해야 한다. unshift()는 한 번에 여러 요소를 배열 앞으로 추가할 수도 있다.
배열의 앞 요소를 제거할 때 변형자 함수가 없다면 요소를 추가할 때와 마찬가지로 비효율적이다. 비효율적인 동작 후에 맨 끝에 불필요한 값이 저장된다. 마지막 콤마가 출력된 것으로 알 수 있다.
shift() 함수를 이용하면 간단히 배열의 맨 처음 요소를 제거할 수 있다.
let nums = [9,1,2,3,4,5]; nums.shift(); console.log(nums);// 1,2,3,4,5
JavaScript
복사
pop()과 shift()는 제거된 요소를 반환하므로 필요하면 이 요소를 변수에 저장할 수 있다.
splice()
시작 인덱스(어느 지점부터 요소를 추가할 것인지)
삭제할 요소의 개수(요소를 추가할 때는 O)
배열에 추가할 요소들
let nums = [1, 2, 3, 7, 8, 9]; let newElements = [4, 5, 6]; nums.splice(3, 0, ...newElements); console.log(nums);// 1,2,3,4,5,6,7,8,9
JavaScript
복사
시작 인덱스 3(nums[3]), 0이므로 요소 추가, 그 다음부터는 추가하려는 요소 목록을 자유롭게 제공하면 된다.
// splice() : 중간에 삭제let nums = [1, 2, 3, 100, 200, 300, 400, 4, 5]; nums.splice(3, 4); console.log(nums);// 1,2,3,4,5
JavaScript
복사
시작 인덱스 3(nums[3])부터 요소 4개를 삭제한다.
sort() 함수가 배열 요소를 순서대로 정렬하며 특히 문자열을 정렬할 때 유용하다.
// sort() 숫자 정렬 함수function compare(num1, num2) { return num1 - num2; } let nums = [3, 1, 2, 100, 4, 200]; nums.sort(compare); console.log(nums);// 1,2,3,4,100,200
JavaScript
복사
배열을 만들지 않는 반복자 함수로 forEach() 함수가 있다. 배열의 모든 요소에 인자로 받은 함수를 호출한다.
function square(num) { console.log(num, num * num); } let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; nums.forEach(square);
JavaScript
복사
every()는 불린 함수를 배열에 적용해 배열의 모든 요소가 참이면 true를 반환한다.
// every() : 불린 함수를 배열에 적용, 모든 요소가 참이면 true 반환.function isEven(num) { return num % 2 == 0; } let nums = [2, 4, 6, 8, 10]; let even = nums.every(isEven); if (even) { console.log("all numbers are even"); } else { console.log("not all numbers are even"); }
JavaScript
복사
some() 함수는 배열 요소 중에 한 요소라도 인자로 받은 불린 요소의 기준을 만족하면 true를 반환한다.
// some() : 불린 함수를 배열에 적용, 하나라도 요소가 참이면 true 반환.function isEven(num) { return num % 2 == 0; } let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let someEven = nums.some(isEven); if (someEven) { console.log("some numbers are even"); } else { console.log("not all numbers are even"); } nums = [1, 3, 5, 7, 9]; someEven = nums.some(isEven); if (someEven) { console.log("some numbers are even"); } else { console.log("no numbers are even"); }
JavaScript
복사
reduce() 함수를 이용해 문자열을 연결할 수도 있다.
// reduce() : 문자열도 연결할 수 있다.function concat(accumulatedString, item) { return accumulatedString + item; } let words = ["the ", "quick ", "brown ", "fox "]; let sentence = words.reduce(concat); console.log(sentence);// the quick brown fox
JavaScript
복사
 문자열에 map() 사용
function first(word){ return word[0]; } let words = ["for", "your", "information"] let acronym = words.map(first) console.log(acronym.join(""));// "fyi"
JavaScript
복사
toString() 을 이용해 요소를 출력하면 콤마가 표시되므로 공백문자열을 분리자로 사용하도록 join()을 호출
filter()는 불린 함수를 만족하는 요소를 포함하는 새로운 배열을 반환한다.
// filter() : 불린 함수를 만족하는 요소를 포함하는 새로운 배열을 반환function isEven(num) { return num % 2 == 0; } function isOdd(num) { return num % 2 != 0; } let nums = []; for (let i = 0; i < 20; ++i) { nums[i] = i + 1; } let evens = nums.filter(isEven); console.log("Even numbers: "); console.log(evens); let odds = nums.filter(isOdd); console.log("Odd numbers: "); console.log(odds);
JavaScript
복사
이차원 베열
Array.matrix = function (numrows, numcols, initial) { let arr = []; for (let i = 0; i < numrows; ++i) { let columns = []; for (let j = 0; j < numcols; ++j) { columns[j] = initial; } arr[i] = columns; } return arr; }; let arr = Array.matrix(3, 2, 3); console.log(arr);
JavaScript
복사

CH2 배열

2.8 객체에 포함된 배열

한 주 동안 관찰된 가장 높은 온도를 저장하는 객체를 만든다. 새 온도를 추가하는 기능, 저장된 온도의 평균을 계산하는 기능을 포함한다.
function weekTemps() { this.dataStore = []; this.add = add; this.average = average; } function add(temp) { this.dataStore.push(temp); } function average() { let total = 0; for (let i = 0; i < this.dataStore.length; ++i) { total += this.dataStore[i]; } return total / this.dataStore.length; } let thisWeek = new weekTemps(); thisWeek.add(52); thisWeek.add(55); thisWeek.add(61); thisWeek.add(65); thisWeek.add(55); thisWeek.add(50); thisWeek.add(52); thisWeek.add(49); console.log(thisWeek.average());
JavaScript
복사

2.9 연습문제

#1. 객체에 학생들의 점수 집합을 저장하는 grades 객체를 만드시오. 점수를 추가하는 함수, 학생의 평균 점수를 출력하는 기능을 객체에 추가하시오.
function grades() { this.dataStore = []; this.add = add; this.average = average; } function add(grade) { this.dataStore.push(grade); } function average() { let total = 0; for (let i = 0; i < this.dataStore.length; ++i) { total += this.dataStore[i]; } return total / this.dataStore.length; } let grade = new grades(); grade.add(800); grade.add(1000); grade.add(1200); grade.add(1400); console.log(grade.average());// 1100
JavaScript
복사
점수를 추가하기 위해 dataStore라는 배열에 push를 이용하였다. 평균 점수는 배열의 모든 요소를 더한다음 배열의 요소 개수로 나눈 값을 반환하여 그 값을 console.log로 출력했다.
#2. 배열의 단어 집합을 저장한 다음 배열의 내용을 정방향 또는 역방향으로 출력하는 기능을 구현하시오.
let arr = ["D", "C", "R", "L", "J"]; console.log(arr); console.log(arr.reverse());
JavaScript
복사
#3. 이차원  배열을 이용해 월간 온도 자료를 저장하도록 weeklyTemps 객체를 고치시오. 월간 평균, 지정한 주의 평균, 모든 주의 평균을 출력하는 함수를 만드시오.
function weekTemps() { this.dataStore = Array.matrix(4, 7, 0);// 이차원 배열 4주, 7일this.add = add; this.wAverage = wAverage; this.wAverageAll = wAverageAll; this.mAverage = mAverage; } Array.matrix = function (numrows, numcols, initial) { let arr = []; for (let i = 0; i < numrows; ++i) { let columns = []; for (let j = 0; j < numcols; ++j) { columns[j] = initial++; } arr[i] = columns; } return arr; }; function add(temp) { this.dataStore.push(temp); } function wAverage(i) { let total = 0; if (0 < i && i < this.dataStore.length) { // 자연수만 받기 > 정규표현식 사용for (let j = 0; j < this.dataStore[i - 1].length; ++j) { total += this.dataStore[i - 1][j]; } return total / this.dataStore[i - 1].length; } else { return "1 ~ " + this.dataStore.length + " 주로 입력하세요"; } } function wAverageAll() { let total = 0; let arr = []; for (let i = 0; i < this.dataStore.length; ++i) { for (let j = 0; j < this.dataStore[i].length; ++j) { total += this.dataStore[i][j]; } arr.push(i + 1 + "주의 평균 : " + total); total = 0;// 주간 총합 초기화 } return arr; } function mAverage() { let total = 0; let mTotal = 0; for (let i = 0; i < this.dataStore.length; ++i) { for (let j = 0; j < this.dataStore[i].length; ++j) { total += this.dataStore[i][j]; } mTotal += total; total = 0;// 주간 총합 초기화 } return mTotal / (this.dataStore.length * this.dataStore[0].length); } let thisWeek = new weekTemps(); console.log(thisWeek.wAverage(1));// 첫째 주 평균console.log(thisWeek.wAverageAll());// 모든 주 평균console.log(thisWeek.mAverage());// 월간 평균
JavaScript
복사

CH3 리스트

3.1 리스트 ADT

리스트는 위치를 가리키는 프로퍼티를 포함한다. 리스트에는 front, end 프로퍼티가 있다. next() 함수로 리스트의 현재 요소에서 다음 요소로 이동할 수 있으며 prev() 함수로 현재 요소에서 이전 요소로 이동할 수 있다. moveTo(n) 함수를 이용하면 n 번째 위치로 한 번에 이동할 수 있다. currPos() 함수는 리스트의 현재 위치를 가리킨다.

3.1 List 클래스 구현

생성자 함수 정의
function List() { this.listSize = 0; this.pos = 0; this.dataStore = []; this.clear = clear; this.find = find; this.toString = toString; this.insert = insert; this.append = append; this.remove = remove; this.front = front; this.end = end; this.prev = prev; this.next = next; this.length = length; this.currPos = currPos; this.moveTo = moveTo; this.getElement = getElement; this.contains = contains; }
JavaScript
복사

3.2.1 Append: 리스트에 요소 추가

리스트의 다음 가용 위치(listSize)에 새 요소 추가하는 함수이다.
function append(element) { this.dataStore[this.listSize++] = element; }
JavaScript
복사

3.2.2 Find: 리스트의 요소 검색

remove()는 가장 구현이 어렵다. 삭제하려는 요소를 찾은 다음 그 요소를 삭제하고 나머지 요소를 왼쪽으로 이동시켜 자리를 메워야 한다. 우선 요소를 찾는 헬퍼 함수 find()를 구현한다.
// find() : remove는 삭제할 요소를 찾고, 요소를 삭제하고, 나머지 배열 요소를 왼쪽으로 이동시켜 자리를 메운다. 삭제할 요소를 찾을 헬퍼 함수function find(element) { for (let i = 0; i < this.dataStore.length; ++i) { if (this.dataStore[i] == element) { return i; } } return -1; }
JavaScript
복사

3.2.3 Remove: 리스트의 요소 삭제

find()는 루프를 돌면서 요소를 검색하고 발견하면 요소의 위치를 반환한다. 찾지 못하면 -1 을 반환한다. remove()는 find()의 반환값으로 에러를 검사한다. 이 반환값을 splice()에 넘겨주어 원하는 요소를 삭제한 다음 배열을 연결한다. 요소를 삭제했다면 true, 못했다면 false를 반환한다.
// remove() : find()의 반환값을 splice 함수에 넘겨주어 원하는 요소를 삭제한 다음 dataStore 배열을 연결한다. 요소를 삭제하면 true, 못하면 false 반환function remove(element) { let foundAt = this.find(element); if (foundAt > -1) { this.dataStore.splice(foundAt, 1); --this.listSize; return true; } return false; }
JavaScript
복사

3.2.4 Length: 리스트의 요소 개수

function length() { return this.listSize; }
JavaScript
복사

3.2.5 toString: 리스트의 요소 확인

function toString(){ return this.dataStore; }
JavaScript
복사

# 중간 테스트 코드

// 리스트 중간 테스트function List() { this.listSize = 0; // this.pos = 0;this.dataStore = []; // this.clear = clear;this.find = find; this.toString = toString; // this.insert = insert;this.append = append; this.remove = remove; // this.front = front;// this.end = end;// this.prev = prev;// this.next = next;this.length = length; // this.currPos = currPos;// this.moveTo = moveTo;// this.getElement = getElement;// this.contains = contains; } function append(element) { this.dataStore[this.listSize++] = element; } // find() : remove는 삭제할 요소를 찾고, 요소를 삭제하고, 나머지 배열 요소를 왼쪽으로 이동시켜 자리를 메운다. 삭제할 요소를 찾을 헬퍼 함수function find(element) { for (let i = 0; i < this.dataStore.length; ++i) { if (this.dataStore[i] == element) { return i; } } return -1; } // remove() : find()의 반환값을 splice 함수에 넘겨주어 원하는 요소를 삭제한 다음 dataStore 배열을 연결한다. 요소를 삭제하면 true, 못하면 false 반환function remove(element) { let foundAt = this.find(element); if (foundAt > -1) { this.dataStore.splice(foundAt, 1); --this.listSize; return true; } return false; } function length() { return this.listSize; } function toString() { return this.dataStore; } let names = new List(); names.append("C"); names.append("R"); names.append("B"); console.log(names.toString()); names.remove("R"); console.log(names.toString());
JavaScript
복사

3.2.6 Insert: 리스트에 요소 삽입

insert() 는 리스트의 기존 요소 뒤에 새로운 요소를 삽입하게 된다. find로 기존 요소의 위치를 찾아 해당 위치 +1 에 요소를 추가한 다음 listSize를 1만큼 증가시킨다.
function insert(element, after) { let insertPos = this.find(after); if (insertPos > -1) { this.dataStore.splice(insertPos + 1, 0, element); ++this.listSize; return true; } return false; }
JavaScript
복사

3.2.7 리스트의 모든 요소 삭제

clear()는 delete 명령어로 배열을 삭제한다음 빈 배열을 다시 만든다. listSize와 pos도 0(시작 위치)으로 초기화한다.
function clear() { delete this.dataStore; this.dataStore.length = 0; this.listSize = this.pos = 0; }
JavaScript
복사

3.2.8 Contains: 리스트에 특정 값이 있는지 판단

function contains(element) { for (let i = 0; i < this.dataStore.length; ++i) { if (this.dataStore[i] == element) { return true; } } return false; }
Java
복사

3.2.9 리스트 탐색

function List() { this.listSize = 0; this.pos = 0; this.dataStore = []; // this.clear = clear;// this.find = find;// this.toString = toString;// this.insert = insert;this.append = append; // this.remove = remove;this.front = front; this.end = end; this.prev = prev; this.next = next; // this.length = length;this.currPos = currPos; this.moveTo = moveTo; this.getElement = getElement; // this.contains = contains; } // @ : 리스트 추가용function append(element) { this.dataStore[this.listSize++] = element; } // 3.2.9function front() { this.pos = 0; } function end() { this.pos = this.listSize - 1; } function prev() { if (this.pos > 0) { --this.pos; } } function next() { if (this.pos < this.listSize - 1) { ++this.pos; } } function currPos() { return this.pos; } function moveTo(position) { this.pos = position; } function getElement() { return this.dataStore[this.pos]; } let names = new List(); names.append("C"); names.append("R"); names.append("Cy"); names.append("J"); names.append("B"); names.append("D"); // 첫번째 요소로 이동 names.front(); console.log(names.getElement()); // 한 요소 뒤로 이동 names.next(); console.log(names.getElement()); // 두 요소 뒤로 이동했다가 한 요소 앞으로 이동 names.next(); names.next(); names.prev(); console.log(names.getElement());// C
JavaScript
복사

3.3 리스트와 반복

반복자를 이용하면 List 클래스 내부 저장소를 직접 참조하지 않고 리스트를 탐색할 수 있다. 리스트의 front, end, prev, next, currPos를 이용해 반복자를 구현할 수 있다.
반복자는 배열의 인덱스에 비해 아래의 장점이 있다.
리스트 요소에 접근할 때 내부 데이터 저장소가 무엇인지 걱정할 필요가 없다.
리스트에 새 요소를 추가했을 때 현재 인덱스가 쓸모 없는 값이 되는 반면 반복자를 이용하면 리스트가 바뀌어도 반복자를 갱신할 필요가 없다.
List 클래스에 사용하는 데이터 저장소의 종류가 달라져도 이전과 같은 방식으로 요소에 접근할 수 있다.
반복자 예제
for (names.front(); names.currPos() < names.length(); names.next()) { console.log(names.getElement); }
JavaScript
복사
현재 위치를 리스트 앞으로 설정(front())한다. 그리고 currPos() 가 리스트 길이보다 작을 때 루프를 반복한다. 루프를 돌 때마다 next()로 한 요소씩 전진한다.
반대 방향 탐색 예제
for (names.end(); names.currPos() >= 0; names.prev()) { console.log(names.getElement); }
JavaScript
복사
현재 위치를 마지막 요소로 한다.(end()) prev()를 이용하여 현재 위치가 0보다 크거나 같을 때 현재 위치를 뒤로 이동시킨다.
리스트를 탐색할 때만 반복자를 사용해야 하며 요소 추가/삭제에는 사용하면 안된다.

3.4 리스트 기반 애플리케이션

비디오 대여 상점을 운영할 수 있는 시스템에서 리스트를 어떻게 활용할 수 있는지 알아본다.

3.4.1 텍스트 파일 읽기

1.
The Godfather
2.
The Godfather: Part II
3.
The Dark Knight
6.
The Lord of the Rings: The Return of the King
14.
The Lord of the Rings: The Two Towers
16.
GoodFellas
위 내용으로 텍스트 파일을 만든다.
let fs = require("fs"); fs.readFile("films.txt", "utf8", function (err, data) { let movies = data.split("\n"); console.log(movies); });
JavaScript
복사
File System 모듈 - 한 눈에 끝내는 Node.js. 파일 처리와 관련된 작업을 하는 모듈로, 보통 FileSystem을 줄여서 fs 모듈이라고 줄여 부릅니다.(책에 있는 코드와 다릅니다.)
텍스트 파일의 내용이 배열로 저장될 때 개행 문자가 공백으로 치환되므로 문자열 배열에서 문제가 될 수 있다. 따라서 trim()을 이용해 각 요소의 공백을 제거하는 루프를 추가한다.
function createArr(file) { let fs = require("fs"); let arr = fs.readFile(file, "utf8", function (err, data) { let arr = data.split("\n"); // console.log(movies);for (let i = 0; i < arr.length; ++i) { arr[i] = arr[i].trim(); } return arr; }); return arr; }
JavaScript
복사

3.4.2 리스트로 상점을 관리하기

movies 배열의 내용을 리스트로 저장한다.
let movieList = new List(); for (let i = 0; i < movies.length; ++i) { movieList.append(movies[i]); } function displayList(list) { for (list.front(); list.currPos() < list.length(); list.next()) { console.log(list.getElement()); } }
JavaScript
복사
displayList()가 문자열 등 네이티브 형식을 포함하는 리스트와는 잘 동작하지만 Customer 객체에서 잘 작동하지 않아 개선이 필요하다.
function displayList(list) { for (list.front(); list.currPos() < list.length(); list.next()) { if (list.getElement() instanceof Customer) { console.log( list.getElement()["name"] + ", " + list.getElement()["movie"] ); } else { console.log(list.getElement()); } } }
JavaScript
복사
instanceof 연산자를 이용해 Customer 객체인지 하나씩 확인하고 Customer 객체면 두 프로퍼티를 인덱스로 활용해 고객이 빌린 영화 이름을 가져온다. 해당 객체가 아니면 요소를 그대로 반환한다.
let customers = new list(); function Customer(name, movie) { // 고객명과 고객이 빌린 영화 이름을 포함하는 객체 생성자 함수this.name = name; this.movie = movie; } function checkOut(name, movie, filmList, customerList) {// 고객이 영화를 대여하는 기능의 함수if (movieList.contains(movie)) {// 영화를 이용할 수 있으면 상점 영화 목록에서 지우고 고객의 영화 목록에 추가한다.let c = new Customer(name, movie); customerList.append(c); filmList.remove(movie); } else { console.log(movie + " is not available."); } }
JavaScript
복사
checkOut() 은 영화를 대여할 수 있는지 확인한다. 대여할 수 있는 상태면 영화 제목, 고객명을 이용해 Customer 객체를 만든다. 만든 객체를 고객 리스트로 추가하고 영화 리스트에서 대여할 영화를 삭제한다. 대여할 수 없는 상태면 간단한 메시지를 출력한다.
checkOut()을 테스트하는 코드
let movies = createArr("films.txt"); let movieList = new List(); let customers = new List(); for (let i = 0; i < movies.length; ++i) { movieList.append(movies[i]); } console.log("Available movies: \n"); displayList(movieList); checkOut("Jane Doe", "The Godfather", movieList, customers); console.log("\nCustomer Rentals: \n"); displayList(customers);
JavaScript
복사
실행하면 "The Godfather"가 삭제된 영화 목록이 출력되고 고객이 대여한 영화 리스트가 출력된다.