JavaScript 배열 메소드 - map(), filter(), find(), reduce()

yojuyoon·2020년 7월 6일
7

TIL👌

목록 보기
9/23
post-thumbnail

.map

map메소드는 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출한 결과를 모아 새로운 배열을 반환한다.

const arrayA = [2, 4, 5, 7, 8];

const mapA = arrayA.map(x => x * 2);

console.log(mapA);
//[4, 8, 10, 14, 16]

arr.map(callback(currentValue[ ,index [, array]]) [,thisArg])

  • callback : 새로운 배열 요소를 생성하는 함수안에 세가지 인수를 가진다.
- currentValue : 처리할 현재 요소
- index : 처리할 현재 요소의 인덱스
- array : map()을 호출한 배열
  • thisArg : callback을 실행할 때 this로 사용되는 값

즉 map 함수는 callback함수를 각각의 요소에 대해 한번씩 순서대로 불러 그 함수의 반환값으로 새로운 배열을 만든다. callback 함수는 배열 값이 들어있는 인덱스에 대해서만 호출되며, 값이 삭제되거나 값이 할당/정의되지 않은 인덱스에 대해서는 호출되지 않는다.

['1', '2', '3'].map(parseInt);
//결과는 [1, NaN, NaN]이다.

왜냐하면 parseInt 함수는 보통 하나의 인자만 사용하지만, 두개를 받을 수 있다. 그러나 첫번째 인자는 변환하고자 하는 표현이 되고, 두번째는 숫자로 변환할 때 사용할 진법이 된다.
다시 말해 parseInt는 parseInt( string, n ) 의 문법을 가지는데 이 때 string을 n진법일 때의 값으로 바꾼다. 따라서 위와 같이 혼란스러운 결과를 도출할 수 있다. 

//배열에서 문자열 길이만 획득하기
const arrA = ['hello' ,'my', 'name', 'is', 'yoju'];
const arrB = arrA.map(str => {
return str.length;
});
console.log(arrB);
//arrA에는 문자열만, arrB에는 문자열의 길이만 담겨있다.
map함수는 콜백 함수의 리턴을 모아서 새로운 배열을 만드는 것이 목적

그렇다면 map 함수 대신 forEach를 쓰면 어떨까?
둘의 차이점은 무엇일까..? 위 함수 예제중 배열에서 문자열 길이만 획득하는 함수를 forEach로 구현해보면

const arrA = ['hello' ,'my', 'name', 'is', 'yoju'];
const arrB =[];
arrA.forEach(srt =>  { arrB.push(str.length);
});
console.log(arrB); //[3, 5, 7, 1]
//상위 스코프 변수를 수정하면서 사이드 이펙트를 가지게 된다.

map은 부모 스코프 영역을 건드리지 않고 콜백 함수만으로 목적을 달성하지만, forEach는 그렇지 않다. 따라서 목적에 따라 다르게 사용하는 것이 좋다.

map함수도 filter함수와 같이 오브젝트를 컨트롤 할 수 있다.

function list() {
  let listJson = [{name : "멍멍이", salary : 6000000},
                  {name : "야옹이", salary : 2000000},
                  {name : "짹짹이", salary : 900000},
                  {name : "개굴이", salary : 8000000},
                  {name : "왈왈이", salary : 5000000},
                  {name : "꿀꿀이", salary : 3000000}];
  
  let newJson = listJson.map((element, index) => {
    console.log(element);
    let returnObj = {}
    returnObj[element.name] = element.salary;
    return returnObj;
  });
  console.log("newObj");
  console.log(newJson);
};
list();

//결과값
newObj
[{name: "멍멍이", salary: 6000000},
 {name: "야옹이", salary: 2000000},
 {name: "짹짹이", salary: 900000},
 {name: "개굴이", salary: 8000000},
 {name: "왈왈이", salary: 5000000},
 {name: "꿀꿀이", salary: 3000000}];
 
//새 배열을 만들고 기존의 배열은 변하지 않는다.

MDN : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map

.filter

filter 메소드는 주어진 함수의 테스트를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.

const words = ['banana', 'apple', 'watermelon', 'pear', 'cherry', 'strawberry'];
const result = words.filter(word => word.length > 6);
console.log(result);
//["watermelon", "strawberry"]

arr.filter(callback(element[, index[, array]])[, thisArg])

  • callback : 각 요소를 시험할 함수. true를 반환하면 요소를 유지하고, false를 반환하면 버린다. 다음 세가지 매개변수를 받는다.

    	- element : 처리할 현재 요소
    • index : 처리할 현재 요소의 인덱스
    • array : filter를 호출한 배열
  • thisArg : callback을 실행할 때 this로 사용하는 값.

//filter함수로 차집합 구하기
const arrA = ['3', '4', '3', '5', '7', '9', '4'];
const arrB = ['4', '2', '5', '7', '1', '2'];

const difference = arrA.filter( x => !arrB.includes(x));

console.log(difference);

//검색 조건에 따른 배열 필터링(쿼리)
const fruits = ['banana', 'apple', 'orange', 'pear', 'grapes', 'strawberry'];

const filterItems = (query) => {
  return fruits.filter((el) => 
     el.toLowerCase().indexOf(query.toLowerCase()) > -1
  	);
  }


console.log(filterItems('ap')); // ['apple', 'grapes']
console.log(filterItems('an')); // ['banana', 'mango', 'orange']

MDN : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

.find

find 메소드는 주어진 판별 함수를 만족하는 첫번째 요소의 값을 반환한다. 그런 요소가 없다면 undefined를 반환한다.

const arrA = [5, 12, 4, 6, 3, 33];

const found = arrA.find(element => element > 10);

console.log(found); // 12

arr.find(callback[, thisArg])

  • callback : 배열의 각 값에 대해 실행할 함수. 아래의 세 인자를 받는다.

    	- element : 콜백 함수에서 처리할 현재 요소
    • index : 콜백 함수에서 처리할 현재 요소의 인덱스
      - array : find 함수를 호출한 배열
  • thisArg : 선택항목. 콜백이 호출될 때 this로 사용할 객체

//속성 중 하나를 사용하여 배열에서 객체 찾기

const inventory = [
  {name : 'apples', quantity : 2},
  {name : 'bananas', quantity : 4},
  {name : 'cherries', quantity : 9}
  ];

const result = inventory.find(fruit => fruit.name === 'cherries');

console.log(result); //  {name : 'cherries', quantity : 9}

MDN : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/find

.reduce

reduce메소드는 각 요소에 대해 주어진 reducer함수를 실행하고 하나의 결과값을 반환한다.

const arrA = [1, 2, 3, 4, 5]
const reducer = (accumulator, currentValue) => accumulator + currentValue;

console.log(arrA.reduce(reducer));//15

리듀서 함수는 네개의 인자를 가진다.

  • 누산기 (accumulator - acc)
  • 현재값 (cur)
  • 현재 인덱스 (idx)
  • 원본 배열 (src)

리듀서 함수의 반환 값은 누산기에 할당되고, 누산기는 순회중 유지되므로 결국 최종 결과는 하나의 값이 된다. 즉 반환 값이 결과 값.

리듀스 메소드는 다른 메소드와는 다르게 콜백 함수와 initialValue라는 두번째 인자를 넣을 수 있다. 또 reduce의 리턴은 배열이 될 수 도, 요소 하나의 값이 될 수도, 사용자가 원하는 값이 값 뭐든지 될 수 있다.

//배열 요소의 합 계산하기
let arr = [9, 2, 8, 5, 7];
let sum = arr.reduce((pre, value) => {
	return pre + value; 
});
console.log(sum); //31

// 정수 배열에서 5의 배수인 정수만 모으기
let arr = [10, 100, 3, 4, 50, 7];
let arrB = arr.reduce((pre, value) => {
  if (value % 5 === 0) {
    pre.push(value);
  }
  return pre;
}, []);
console.log(arrB);//[10, 100, 50]

.find 메소드는 찾으면 더이상 콜백 함수가 불리지 않지만, reduce는 요소의 수 만큼 항상 호출되는 단점도 있다. 중요한 것은 상황에 맞는 메소드를 적절하게 활용하는 것!

콜백 함수 호출 순서

reduce의 두번째 인자인 initialValue를 생략하였기 때문에 첫번째 콜백에 pre는 첫번째 요소인 9가 전달 되고 이후 콜백에서의 pre는 이전 콜백의 리턴이 된다.

MDN : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

참고 블로그 : https://bblog.tistory.com/300

profile
하고싶은게 많은 사람. Front-end Developer

0개의 댓글