JavaScript_배열메소드(Array_Method)_배열 변환(callback method)

nd098pkc·2022년 7월 9일
0

개요

우리에게 주어진 배열형태의 데이터는 그 자체로 유용할 때도 있겠지만 어떤 방식으로든 새롭게 가공하고 변경해야할 경우가 더 많을 것입니다. 사용자가 자주 활용할만한 배열 변환에 대해서는 JavaScript 자체적으로 method가 이미 구현되어 있는 경우가 많아 그 method들에 대해서 한번 정리해보려고 합니다.

콜백 method

map이나 filter같이 callback 함수를 인자로 받는 method에 대해서, MDN에는 사용 구문에

arr.method(callback(currentValue[, index[, array]]) <=('[]'안은 선택이라는뜻)

위와 같이 사용하라고 예시하고 있지만 실제로는 위와 같이 쓰면 안되고

arr.map(callback)

위와 같이 parameter를 생략하고 사용해야합니다.
그러면 해당 callback 함수에는 자동으로 순서대로 value, index, arr가 parameter로 들어가게됩니다

parameter를 선택적으로 넘겨주려면

arr.map((val,idx)=>callback(val,idx)) 

위와 같이 화살표 함수 표현식으로 넘겨주어야합니다.
이어서 기본적으로 서술할 사용 예제도 화살표 함수를 사용하여 표현하겠습니다.

1. map

map은 배열의 요소값이나 인덱스를 기준으로 배열을 새롭게 변화시키고 싶을 때 사용하게 되는 method입니다.
만약 map이라는 method 없이 새로운 배열을 만들려면 다음과 같이 표현해야할것입니다.

let newArr = []
for(let i=0;i<arr.length;i++){
	newArr.push(callback(arr[i], i)) // callback: 변화시킬 규칙을 담은 함수 
}

여기서 map은 새로운 배열을 초기화시켜주는 단계와 반복문을 돌리는 단계를 생략시켜 준다고 생각해주시면 되겠네요

사용법 :
let newArr = arr.map((val, idx, array)=>callback(val,idx,array))

 0. newArr: 변환된 결과를 받을 변수
 1. arr: 변환할 배열
 2. callback: 배열을 순회하며 실행할 함수
 3. val: 요소
 4. idx: 인덱스
 5. array: 순회중인 배열(=arr와 동일)

기본적으로 parameter를 넘겨주는 부분에 3개까지 변수를 추가해줄 수 있습니다. 각각 자동으로 첫번째 parameter는 요소가 지정되며 두번째 parameter에는 index, 세번째 parameter에는 map의 대상이되는 배열이 지정되게 됩니다.
parameter를 (idx, arr, val) 이런식으로 써준다고 해도 idx에는 요소가, arr에는 인덱스가, val에는 배열이 할당되게 됩니다. 제일 처음 배울때 헷갈렸던 기억이 나네요..

callback 함수 부분에는 다른 함수를 가져와도 괜찮지만 직접 써주기도 하는데요

예제 :
let arr=['a','b','c']
let newArr = arr.map((val, idx)=> [val, idx]) //newArr = [['a',0],['b',1],['c',2]]

예제에서는 기존 요소값을 인덱스와 묶어서 표현될 수 있도록 변경해보았습니다. 이와 같이 변환시키고 싶은 규칙이 배열의 각 요소와 인덱스에 따라 정해진 규칙이라면 언제든 map을 사용해서 새로운 배열로 변환시킬 수 있습니다.

2.filter

filter는 배열중 일부 조건에 맞는 요소만 걸러내고 싶을 때 사용하는 method입니다. 걸러내는 방법은 기준에 맞는 요소만 true를 반환하게하는 함수를 만드는 것입니다.

filter의 기능을 filter 없이 표현하면 다음과 같을 것입니다.

let newArr = []
for(let i=0;i<arr.length;i++){
	if(callback(val,idx,arr)==true){ callback: 조건에 맞는 요소를 true로 반환하는 함수
	newArr.push(arr[i]) // 
	}
}

map과 마찬가지로 filter도 새로운 배열을 초기화시키고 반복문을 돌리는 부분을 생략시켜줍니다.

사용법 :
let newArr = arr.filter((val, idx, array)=>callback(val,idx,array))

 0. newArr: 변환된 결과를 받을 변수
 1. arr: 변환할 배열
 2. callback: 배열을 순회하며 요소를 check할 함수
 3. val: 요소
 4. idx: 인덱스
 5. array: 순회중인 배열(=arr와 동일)

억지로 노력하지 않으면 filter는 배열의 요소 값을 변화시키지는 않습니다. 배열과 요소, 인덱스를 기준으로 하여 걸러내고 싶은 조건 함수를 잘 만들어주면 내가 원하는 조건에 맞는 요소들만 선별적으로 들어가있는 함수를 반환해줍니다.

예제 : 
let arr=[1, 2, 3, 4, 5, 6, 7, 8, 9]
let newArr1 = arr.filter((val)=>val%2==0) //newArr1 = [2,4,6,8] 
let newArr2 = arr.filter((val,idx)=>idx%2==0) // newArr2 = [1,3,5,7,9]

위 예제에서 newArr1은 요소(val)를 2로 나눈 나머지가 0인가 라는 조건을 기준으로 설정해두었기 때문에 val%2==0을 true로 반환하는, 즉 짝수인 값들만 새로운 배열에 담겨져 나왔고, newArr2는 인덱스(idx)를 2로 나눈 나머지가 0인가 라는 조건을 기준으로 하였기때문에 idx가 짝수인(0,2,4,6,8번 idx) 요소들만 새로운 배열에 담겨져 나왔다고 설명드릴 수 있겠습니다.

메소드체인

배열을 대상으로 하는 많은 method는 배열을 return하기 때문에 return되는 배열을 대상으로 연속적으로 method를 이어나갈 수 있습니다.

예제 1:
let arr = [1,2,3,4,5]
let newArr = arr.map(v=>v+1).fliter(v=>v>3)  //newArr= [4,5,6]
        //기존 배열 요소에 1씩 더해주고 3보다 큰 값만 return

위 예제에서 arr.map(v=>v+1)까지 마친 배열은 [2,3,4,5,6]이 될것입니다.
이 배열을 바로 이어받아 filter(v=>v>3)을 수행하면 최종적으로 3보다 큰값인 [4,5,6]이 반환되어 나오는 것입니다.
물론 filter 또한 배열을 반환하므로 이 뒤에도 배열 method를 계속 이어나갈 수 있게됩니다.
즉, 배열을 반환하는 method끼리는 이어서 연속하여 사용이 가능합니다.

그런데 이 메소드 체인을 사용함에 있어서 원본을 관리하는 측면에서 조금 생각해볼 부분이 있다는 생각이 듭니다.

예제 2-1:
let arr = [5,4,3,2,1]
let newArr = arr.map(v=>v+1).sort()

예제 2-2:
let arr = [5,4,3,2,1]
let newArr = arr.sort().map(v=>v+1)

예제 2-1과 2-2에서 newArr에는 각각 어떤 배열이 담길까요?
아마 두 예제 모두 [2,3,4,5,6]이 나올 것을 쉽게 예상하실 수 있을겁니다.

그런데 차이는 원본이 되는 arr 배열에 있습니다.
sort 함수는 대상이 되는 배열 자체를 변화시켜 반환하는 함수입니다.
하지만 map은 원본배열은 그대로 둔 채, 초기화 된 새로운 배열에 값을 담아 반환합니다.

예제 2-1:
let arr = [5,4,3,2,1]
let newArr = arr.map(v=>v+1).sort() //arr=[5,4,3,2,1]

예제 2-2:
let arr = [5,4,3,2,1]
let newArr = arr.sort().map(v=>v+1) //arr=[1,2,3,4,5]

예제 2-1에서는 먼저 map에서 원본이 아닌 새로운 배열이 반환된 뒤 sort를 적용했기 때문에 원본이 그대로 남아있지만 예제 2-2에서는 원본에 sort를 적용하여 원본이 변경된 뒤 map을 돌렸기 때문에 원본이 sort의 영향을 받아 변경이 되어버렸습니다.
새롭게 받은 배열은 같지만 메소드체인 순서에 따라서 원본이 원하지 않게 변경되는 일이, 혹은 변하지 않는 일이 발생할 수도 있는 것입니다.

원본이 변하는 method: splice, sort, reverse, fill

원본배열을 변화시키면서 배열을 반환하는 method가 많지는 않지만 많지 않은 만큼 놓치기 쉬운 부분일 수 있으니 알아뒀다가 배열 method 활용 시 신경써주면 좋을 것 같습니다.

profile
늦게배운 코딩이 무섭다

0개의 댓글