frontend/javaScript

[js 기초] map, reduce, filter (array와 object에 사용하기)

김포레스트 2023. 8. 16. 13:04

code Up 홈페이지에서 알고리즘 문제풀이를 하다가 reduce 를 만났다.

언뜻 이해가 가지 않아서 정리를 해보려고 한다.

 

근데 reduce만 하기는 심심하니까 map 하고 filter를 함꼐 살펴보도록 한다.

 

사실 책임님이 이 세가지는 잘 알아두라고 해두신적이 있어서

이참에 확실히 알아두는게 좋을거라고 생각 하기도 했다.

하하. 말씀하실 때 진작할걸. 게으른 신입이는 뒤늦게 자신을 책망한다.

 

자그럼 시작!!!

 

1. map

  map 은 배열의 모든 요소를 호출해서 새로운 배열을 만들어낸다. 기본적인 파라미터는  currentValue, index, arr로 세가지 이다. 새로운 배열을 또 만든다니? 무슨말인지 와닿지 않는다. 이럴땐 역시 콘솔찍기.

 

var array = ['Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '];

var arrayResult = array.map(function(crr, idx, arr) {
	return crr; //idx, arr를 차례로 찍어보자
});

console.log("🚀 ~ file: codeup.html:180 ~ arrayResult:", arrayResult);

 

 

** crr 출력화면 **

 

** idx 출력화면 **

 

** arr 출력화면 **

 

idx와 arr를 찍고 나서 이해했다. 

진짜로 새로운 배열에 해당 값을 넣어서 출력해준다는 의미 였다.

그러니 crr 값도, 사실은 원래 있던 arr 배열을 그대로 출력한 것이 아니라, arr 내부에 있던 '값'을 새로운 배열에 담아서 출력해준 것임을 알 수 있다. 

 

펑션 내에서 array 요소들을 지지고 볶은 다음에 그걸 '배열의 형태'로 다시 뱉어내줘!!

할때 쓰면 좋을 것 같다. 

 

한편,

map 함수 내에서는 this를 사용할 수 없다.

var arrayResult = array.map(function(crr, idx, arr) {	
  return this;
});

위와같이 undefined 를 뱉어낼 뿐이다.

map 함수 내에서 this를 사용하고 싶으면, function 다음에 오는 옵션 값에 this를 바인딩해주면 된다.

var arrayResult = array.map(function(crr, idx, arr) {	
  return this.array;
}, this);

** 출력내용 **

짜잔-!

 

+) 애로우 펑션 사용해서 표현하기

var arrayResult = array.map((crr, idx, arr) => this.array, this);

 

2. filter 

일단 w3school 에 나와있는 개념을 읽어보도록 한다.

이 메소드는 map처럼 새로운 배열을 생성해주는 역할을 한다. 그런데, '테스트'를 통과한 요소만 담아준단다. 

그게 뭔소리야.

 

환장한다.

 

한국어로 번역해도 답이없다.

무슨 테스트를 한다는 말인가? 

 

또 콘솔을 찍어보도록 하자.

var array = ['Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '];

var arrayResult = array.filter(function(crr, idx, arr) {
  console.log("🚀 ~ file: codeup.html:176 ~ arrayResult ~ idx:", idx);
  
  return crr; //idx와 arr도 차례로 찍어보자
});

 

** crr 출력결과 **

 

** idx 출력결과 **

 

** arr 출력결과 **

 

 

잠깐! 여기서 이상한점.

 

콘솔 내부에서 index 값을 찍으면 0부터 4까지 바르게 나온다.

그런데, index값을 return 해달라고 해서 찍어보면 

첫번째 요소를 생략하고 두번쨰 요소부터 배열애 담아주는 것을 볼 수 있다.

 

이유가 뭘까

 

여기서 다시 상기시켜봐야 할 개념이 있다.

 

'테스트를 통과한'

'테스트를 통과한'

'테스트를 통과한'

그렇다. 이녀석은 true와 false를 판단한 뒤에 true값만 filtering 해서 반환을 해주는데, 

index의 0값을 false라고 인식하는 것이다..

그래서 매번 첫번째 요소가 false로 간주되어 탈락 해버리는 것이다. 

 

index 값을 반환해서 출력했을 때의 문제이고, 

콜백함수 내에서는 문제없이 출력되니 너무 염려 말도록 하자.

 

어쨌든 인덱스값을 찍어보다가 테스트의 의미를 함께 알아보게 되었다.

그럼 다시 예시를 보자.

 

var array = [true, true, false, true, true];

var arrayResult = array.filter(function(crr, idx, arr) {
	return crr;
});

console.log("🚀 ~ file: codeup.html:180 ~ arrayResult:", arrayResult);

 **출력결과**

진짜 false를 걸러준다.

 

filter 메소드 에서도 map과 동일하게 this  옵션을 바인딩 해서 사용해야 하기 때문에

사용법은 생략한다. 

 

 

 

 

3. reduce

  reduce는 배열 요소에 대한 감속기 역할을 해주는 함수이다. 처음 값부터 끝 값까지 순회하여 그 값을 누적한 뒤에, 누적결과를 반환해 주는 역할을 한다. 하지만 무슨말인지 잘 모르겠다. 누적이라는 말을 들어보니 아마도 배열에 forEach를 안쓰고 싶어서 만들어진 함수는 아닐까~ 하는 합리적의심이 든다.

 

일단 냅다 콘솔을 찍어보도록 하자.

var array = ['Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '];

var arrayResult = array.reduce(function(total, crr, idx, arr) { 
  return total + '\n' + crr + '\n' + idx + '\n-----------';
});

reduce 의 파라미터는 총 네개로 순서대로 누적된 total 값, 현재 값, 인덱스 값, 배열 전체를 반환한다.

 

 

** 출력 내용 **

 

** arr 파라미터만 출력**

 

total 은 딱 한번 첫 요소만 반환 해준다.

crr은 두번째 요소부터 마지막 요소까지 반환 해준다.

index는 두번째 요소의 인덱스 값 부터 반환 해준다.

arr는 초기화 되어있던 원래의 array 배열을 반환 해준다. 

 

아마 헷갈리는 것은 total 값일 것이다.

누적값이라고 하더니.. 왜 첫 요소만 반환하고 끝나는 걸까? 

 

그럼 함수 내부를 이렇게 바꿔주자.

var arrayResult = array.reduce(function(total, crr, idx, arr) { 
  return total += crr;
});

** 출력내용 **

내가 명령하지 않아도 '누적된 값'을 자동 산출하여 반환 해 주는 것이 아니라,

누적값을 도출 할 수 있게 순환을 해준다는 의미인 것 같다.

for 문이나 forEach 같은 반복문을 사용하지 않아도

자동으로 배열을 순회하여 누적값을 반환해주는 것을 볼 수 있다.

 

reduce 함수에는 특이한 옵션이 있는데, 바로 '초기값'을 지정 해줄 수 있다는 것이다.

나는 이미 배열의 첫 요소에 값을 지정 했지만

누적값을 계산할 때 새로운 초기값을 포함하여 순회하겠다는 것이다.

배열에는 새로이 추가되지 않는다는 특징이 있다.

 

예시를 보자. 

var array = ['Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '];

var arrayResult = array.reduce(function(total, crr, idx, arr) { 
  return arr;
}, '초기값');

아까와 같은 배열을 반환할 것이다. 

단, reduce의 옵션 값으로 '초기값'을 새롭게 할당해 줄 것이다. 

 

그렇다면 출력되는 배열은 과연 

['Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '] 일까?

['초기값', 'Red ', 'Orange ', 'Green ', 'Blue ', 'Yellow '] 일까?

 

** 출력화면 **

reduce 함수는 원래의 배열을 수정하지 않는다. 초기값을 지정해줘도 변경되지 않은 배열을 뱉는다.

 

하지만 total 파라미터를 찍어보면 '초기값' 을 반환하고,

누적값을 산출하면 아래와 같이 나온다.

 

 

 

 

+ ) 그렇다면 object에는 어떻게 적용 해볼 수 있을까?

var object = {
  Red : 5,
  Orange : 4,
  Green : 3,
  Blue : 2,
  Yellow : 1 
};

var objectResult = Object.keys(object).reduce(function(total, crr, idx, arr) { 
  return total + '\n' + crr + '\n' + idx + '\n-----------';
});

console.log("🚀 ~ file: codeup.html:158 ~ objectResult:", objectResult);

요렇게 Object.keys 를 사용하면 된다.

 

 

+) 애로우 펑션으로 간단히 한 모습 

var arrayResult = array.reduce((total, crr, idx, arr) => total += crr, '초기값');