Array Cardio Day 1

Woohyun Jang
12 min readOct 8, 2018

--

이번에는 Javascript Array.prototys의 자주 쓰이는 함수들을 사용해보면서 사용법에 익숙해져보는 시간을 가져보려고 한다. React에서는 특히 state값을 변경하지 않고 새로운 객체를 만들어 대체시켜주어야 하기 때문에 새로운 배열을 return해주는 함수들을 잘 사용한다면 React로 코딩하기가 매우 편리해진다.

초기 소스코드는 다음 저장소에 있다.

위 파일을 보면 해결해야 할 문제는 총 8가지가 있다. 주어진 배열이 있고, 그 배열을 javascript Array의 function들로 원하는 모습으로 가공해볼 것이다.

먼저 1번.

Array.prototype.filter() 1. Filter the list of inventors for those who were born in the 1500's

1500년대 태어난 사람들만 필터링하는 문제이다. 위 문제를 해결하기에 가장 적합한 함수는 filter함수이다. filter는 parameter로 callback function을 받고 이 함수는 각 배열의 요소를 테스트한다.

callback(element, index, array){// test}

이렇게 세 인자를 받아 함수 내부 test의 return값이 true일 경우 해당 element를 최종적으로 return할 새 배열의 인자로 추가한다.

위 문제에서는

inventors.filter((inventor, index, array) => {
if(inventor.year > 1499 && inventor.year < 1600) {
return true;
} else {
return false;
}
});

다음과 같이 작성해주면 inventor.year이 1500년대인 데이터만 필터링할 수 있다. 좀 더 간단하게 작성하면

inventors.filter(inventor => {  return inventor.year > 1499 && inventor.year < 1600});

이렇게 해줄 수 있다. 결과를 console.log()로 찍어보면

[ { first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
{ first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 } ]

이렇게 1500년대 생만 출력되는 것을 확인할 수 있다.

2번.

// Array.prototype.map()// 2. Give us an array of the inventors' first and last names

inventors 배열의 이름과 성으로 배열을 만드는 문제이다. 여기에서는 map function을 사용한다. map()은 callback function의 리턴값들로 새로운 배열을 만들어 반환해준다.

각 inventors의 이름과 성으로 이루어진 새로운 배열을 만들기 위해서는

inventors.map(inventor => { return `${inventor.first} ${inventor.last}`;});/* result
[ 'Albert Einstein',
'Isaac Newton',
'Galileo Galilei',
'Marie Curie',
'Johannes Kepler',
'Nicolaus Copernicus',
'Max Planck',
'Katherine Blodgett',
'Ada Lovelace',
'Sarah E. Goode',
'Lise Meitner',
'Hanna Hammarström' ]
*/

다음과 같이 작성해주면 된다. callback function의 return값은 template literal을 사용해 간단하게 표현했다.

3번 문제는 sort()를 사용하는 문제이다.

// Array.prototype.sort()// 3. Sort the inventors by birthdate, oldest to youngest

inventors를 생일기준으로 오래 된 inventor 부터 어린 inventor순으로 정렬하면 된다.

sort함수는 위 함수들(filter, map)과는 다르게 새로운 배열을 만들어 반환하는 것이 아니라 기존의 함수를 정렬만 시켜준다. 또 parameter로 함수를 넘겨주는 것이 필수는 아니다. 만약 아무 함수도 넘겨주지 않고 array.sort()같은 형태로 실행하게 된다면 인자들의 유니코드 순서대로 배열을 정렬시킨다. 함수를 넘겨준다면 해당 함수는 두 개의 인자를 받아 비교하는 compareFunction이어야 한다. 배열에서 비교 할 요소 두 가지를 a, b라고 할 때 compareFunction(a, b)의 return 값이 0보다 작을경우 a를 b보다 앞에 정렬시키고, 0보다 클 경우에는 b를 앞으로 정렬시킨다.

주의할 점은 0일 때는 변경 없이 현재 상태를 유지한다는 점인데 ECMAscript표준은 아니기 때문에 항상 이렇게 동작함을 보장할 수는 없다고 한다.

이번 문제를 해결하기 위해서는

inventors.sort((a, b) => {  return a.year < b.year ? -1 : 1;});/* result
[ { first: 'Max', last: 'Planck', year: 1858, passed: 1947 },
{ first: 'Albert', last: 'Einstein', year: 1879, passed: 1955 },
{ first: 'Katherine', last: 'Blodgett', year: 1898, passed: 1979 },
{ first: 'Lise', last: 'Meitner', year: 1878, passed: 1968 },
{ first: 'Marie', last: 'Curie', year: 1867, passed: 1934 },
{ first: 'Sarah E.', last: 'Goode', year: 1855, passed: 1905 },
{ first: 'Hanna', last: 'Hammarström', year: 1829, passed: 1909 },
{ first: 'Ada', last: 'Lovelace', year: 1815, passed: 1852 },
{ first: 'Isaac', last: 'Newton', year: 1643, passed: 1727 },
{ first: 'Johannes', last: 'Kepler', year: 1571, passed: 1630 },
{ first: 'Galileo', last: 'Galilei', year: 1564, passed: 1642 },
{ first: 'Nicolaus',
last: 'Copernicus',
year: 1473,
passed: 1543 } ]
*/

다음과 같이 작성해주면 된다.

4번 문제는

// Array.prototype.reduce()// 4. How many years did all the inventors live?

모든 inventors 나이의 총 합을 구하는 문제이다. reducer()함수를 사용하며, reduce()는 배열의 각 요소들을 순회하며 하나의 단일 값으로 줄여주는 함수이다. callback function과 초기 값인 initValue를 인자로 받으며 initValue를 정의하지 않으면 첫 번째 요소가 initValue로 사용된다.

callback funtion은 이전 단계까지 연산이 진행된 값인 accumulator와 현재 연산이 진행될 요소인 currentValue, 그 index친 currentIndex와 array로 구성된다.

inventors.reduce((sum, inventor) => {return sum + (inventor.passed - inventor.year);}, 0);// result 861

배열의 모든 나이의 합을 합하기 위해서는 초기 값을 0으로 설정하고 각 inventors의 나이를 합해주었다.

5번문제는 다시 sort() function을 사용하는 문제이다.

// 5. Sort the inventors by years lived

inventors를 오래 살았던 순서대로 정렬하면 된다. 각각의 사망 당시 나이는

inventor.passed - inventor.year

로 구하면 되기 때문에 위 문제를 해결하려면

inventors.sort((a, b) => {return (b.passed - b.year) - (a.passed - a.year);});

다음과 같이 코드를 작성한다. b의 나이가 a의 나이보다 클 경우 b는 a보다 배열의 앞에 정렬시킨다.

다음 문제는 위키피디아에 접속하여 파리에 ‘de’를 포함하고 있는 길들을 list로 만드는 것이다.

// 6. create a list of Boulevards in Paris that contain 'de' anywhere in the name// https://en.wikipedia.org/wiki/Category:Boulevards_in_Paris

위 uri로 접속하면

다음과 같은 페이지가 나온다. 개발자 도구(cmd + option + i)를 키고 console에 명령어를 입력하면 된다. cmd + shift + c키를 이용하면 마우스를 통해 해당 요소를 html파일에서 찾을 수 있다. 우리가 원하는 파리의 길들은 ‘mw-category’라는 클래스 명을 가진 div안에 a tag들로 리스트화 되어있다. 따라서 이들을 모두 선택하려면

document.querySelectorAll('.mw-category a');

이렇게 하면 된다. 해당 결과물은 Array가 아닌 NodeList로, forEach()는 사용이 가능하지만 다른 Array function을 사용할 수 없기 때문에 Array.form()함수를 통해 Array로 변경해준다. 이후에는 filter함수를 통해 해당 요소의 textContent에 ‘de’문자열이 포함되어있는 요소만 필터링 하면 된다.

const list = Array.from(document.querySelectorAll('.mw-category a'));
const result = list.filter(element => {
return element.textContent.includes('de');
}
)
// 7. sort Exercise
// Sort the people alphabetically by last name

7번은 people 배열을 last name을 알파벳순으로 정렬하는 문제이다. people array의 요소는 ‘Beck, Glenn’과 같은 문자열로 구성되어있다.

people.sort((a, b) => {  return a.split(', ')[1] > b.split(', ')[1] ? 1 : -1;});

먼저 각 요소의 last name을 추출해야 한다. 문자열에 splite(‘, ‘) function을 써서 ‘, ‘를 기준으로 문자를 잘라냈다. 잘라낸 결과물의 index 0번은 ‘. ‘앞의 first name이 될 것이기 때문에 last name값이 필요한 우리는 index 1번 값을 사용하여 두 요소의 값을 비교했다. last name의 유니코드값이 작으면 배열의 앞으로 가도록 sorting해주면 된다.

마지막 8번은 배열의 해당 요소가 몇 개가 들어있는지를 카운팅하는 문제이다.

// 8. Reduce Exercise// Sum up the instances of each of theseconst data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];

결과물은 {name: many, name2: many2}와 같은 형태로 반환해주면 된다.

const result = data.reduce((obj, item) => {  if(!obj[item]) {    obj[item] = 0;  }  obj[item]++;  return obj;}, {});/* result{ car: 5, truck: 3, bike: 2, walk: 2, van: 2 }
*/

초기 값은 빈 객체로 설정해주고, obj의 item을 key값으로 가지는 수가 없으면 새로 만들어 0으로 초기화해준다. 이후 해당 값을 + 1 하여 다음 사이클로 넘겨주면 reduce함수의 리턴 값은 {item: count}형태로 반환된다.

--

--

No responses yet