Deep Dive 27장 배열(2) 고차함수

@hanminss·2022년 1월 19일
0

Deep Dive

목록 보기
15/16
post-thumbnail

고차함수?

  • 함수를 인수로 전달받거나 함수를 반환하는 함수
  • 조건문, 반복문을 지양하고 순수 함수를 사용해 함수형 프로그래밍을 지향하자 !

1. Array.prototpye.sort

배열의 요소를 유니코드 코드 포인트의 순서를 따라 정렬한다. 숫자의 경우도 비교를 위하여 문자열로 변환 후 유니코드 코드 포인트에 따라서 정렬한다. 이 때, 숫자에서 문제가 발생한다.

const arr1 = [2,1];
const arr2 = [10,2];

arr1.sort(); // [1,2]
// 1의 유니코드 코드 포인트 : U+0031
// 2의 유니코드 코드 포인트 : U+0032

arr2.sort(); // [10, 2];
// 10의 유니코드 코드 포인트 : U+0031U+0030
// 2의 유니코드 코드 포인트 : U+0032
// 10의 유니코드 코드 포인트가 2보다 앞서므로 10이 더 앞으로 오게된다.
이 문제를 해결하기 위해  숫자를 비교할 때, sort 메서드에 정렬 순서를 정의하는 비교 함수를 인수로 전달 해야한다.

우선 한 배열을 그냥 sort 해보면 유니코드 코드 포인트에 의해 맨 앞자리 숫자를 기준으로 정렬되고 있는 것을 확인 할 수 있다.

const arr =[40,100,1,5,2,25,10];
arr.sort(); // [1, 10, 100, 2, 25, 40, 5]
sort에 인수로 들어가는 비교함수가 어떻게 작동하는지 보기 위해 콘솔을 찍는 간단한 함수를 넣어보았다.

onst arr =[40,100,1,5,2,25,10];
arr.sort((a,b,c)=>{console.log(a,b,c)});

/*
100 40 undefined
1 100 undefined
5 1 undefined
2 5 undefined
25 2 undefined
10 25 undefined
*/
위 결과로 sort 속 비교 함수는 2개의 인수를 받고 i=0이라 했을 때 순차적으로 a = arr[i+1] b= arr[i] 가 들어가는 것을 확인할 수 있다.

이번엔 리턴값에 따라 결과가 어떻게 바뀌는지 살펴보았다.

// case 1 : 리턴값이 양수일 때
const arr =[40,100,1,5,2,25,10];

arr.sort((a,b)=> 1);

console.log(arr); // [40, 100, 1, 5, 2, 25, 10]

//case 2 : 리턴값이 0 일 때
const arr =[40,100,1,5,2,25,10];

arr.sort((a,b)=> 0);

console.log(arr); // [40, 100, 1, 5, 2, 25, 10]


//case 3 : 리턴값이 음수일 때
const arr =[40,100,1,5,2,25,10];

arr.sort((a,b)=> -1);

console.log(arr); // [10, 25, 2, 5, 1, 100, 40]
case 1 : 리턴값이 양수일 때 : 변함없음

case 2 : 리턴값이 음수일 때 : 변함없음

case 3 : 리턴값이 음일 때 : 배열의 순서가 reverse 되었다.

- > 따라서 sort 함수는 비교함수가 음수를 반환하면 요소의 순서를 바꾼다는 것을 알게되었다.

 

이제 배열을 오름차순으로 정렬하기 위해서 비교함수를 설계해야 한다.

음수가 리턴되면 순서가 바뀌기 때문에  a-b 가 음수이면 순서를 바꿔야 할 것이다.(앞 요소가 더 크다는 뜻)

const arr =[40,100,1,5,2,25,10];
arr.sort((a,b) => a-b); //[1, 2, 5, 10, 25, 40, 100]
// 오름차순 정렬

const arr =[40,100,1,5,2,25,10];
arr.sort((a,b) => b-a); //[100, 40, 25, 10, 5, 2, 1]
// 내림차순 정렬

2. Array.prototpye.forEach

forEach 메서드는 반복문을 추상화한 고차 함수로서 내부에서 반복문을 통해 자신을 호출한 배열을 순회하면서 수행해야 할 처리를 콜백 함수로 전달 받아 반복 호출한다. forEach는 콜백 함수를 호출하면서 3개의 인수를 전달한다. forEach의 첫번째 인수로는 콜백함수를 받아오고 필요 시 두번째 인수로는 thisArg 를 받아 this를 바인딩 할 수 있다.

const arr = [1,2,3];

arr.forEach((item, index, arr) => {
    console.log(`요소값: ${item}, 인덱스: ${index}, this: ${arr}`)
});

/*
요소값: 1, 인덱스: 0, this: 1,2,3
요소값: 2, 인덱스: 1, this: 1,2,3
요소값: 3, 인덱스: 2, this: 1,2,3
*/
forEach 메서드의 반환값은 언제나 undefined이다.

const arr = [1,2,3];
console.log(arr.forEach(() => 1)); // undefiend

3. Array.prototpye.map

map 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출하여 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다. 원본 배열은 변경되지 않는다. map 메서드는 콜백 함수를 호출하면서 3개의 인수를 전달한다.

const arr = [1,2,3];
const arrPow = arr.map((item) => item**2); //[1, 4, 9]


arr.map((item,index,arr) =>{
    return item+index;}); // [1, 3, 5]

4. Array.prototpye.filter

filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출하여 콜백 함수의 반환값이 true인 요소들로만 구성된 새로운 배열을 반환한다. 원본 배열은 변경되지 않는다. filter 메서드는 콜백 함수를 호출하면서 3개의 인수를 전달한다.

const arr = [1,2,3,4,5,6,7,8,9,10];

arr.filter((item) => item/2 < 3); // [1, 2, 3, 4, 5]

arr.filter((_,index) => index > 5); // [7, 8, 9, 10]

5. Array.prototype.reduce

reduce 메서드는 자신을 호출한 배열을 모든 요소를 순회하며 인수로 전달받은 콜백 함수를 반복 호출하여 콜백 함수의 반환값을 다음 순회 시에 콜백 함수 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 하나의 결과값을 만들어 반환한다. 원본 배열은 변경되지 않는다. reduce 메서드는 2개의 인수를 받으며 첫번째 인수로 콜백함수, 두번째 인수로 초기값을 받게 된다. 콜백함수는 4개의 인수를 받으며 첫번째는 초기값 혹은 전 순회로 부터 받은 값 , 두번쨰는 현재 인덱스의 value, 세번째는 index 번호를 저장하며 네번째는 this가 전달된다.

  • 배열의 합 구하기
const arr = [1,2,3,4,5];

arr.reduce((acc,cur) => {
    acc+=cur;
    return acc;}, 0); // 15
  • 최대 값 구하기
const arr = [100, 2133, -3, 21, 5, 103]

arr.reduce((acc, cur) =>  (acc > cur ? acc : cur), -9999); // 2133
- 중복요소 제거

const arr = [1,2,3,4,3,2,1,2,3,4,5,6,5,3,2,1,2,3,4,2,5,2,1,2];

arr.reduce((acc,cur,i, ary) => {
    if (ary.indexOf(cur) === i) acc.push(cur);
    return acc;},[]); // [1, 2, 3, 4, 5, 6]

6. Array.prototype.some

some 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출한다. 이때 콜백 함수의 반환값이 한번이라도 true 가 나오면 true 를 반환하고 아니면 false를 반환한다. some 메서드도 콜백 함수를 호출하면서 3개의 인수를 전달한다.( item, index, arr)

const arr = [10, 20, 30];

arr.some((item) => item < 0); // false
arr.some((item) => item > 20); // true

7. Array.prototype.every

every 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백함수를 호출하며 콜백 함수의 반환값이 모두 true면 true를 아니면 fals를 반환한다. every 메서드도 콜백 함수를 호출하면서 3개의 인수를 전달한다.( item, index, arr)

const arr = [10, 20, 30];

arr.every((item) => item>0); // true
arr.every((item) => item>10); // false

8. Array.prototype.find ES6

find 메서드는 자신을 호출한 배열을 순회하며 콜백 함수를 호출하여 반환값이 true인 첫 번째 요소를 반환한다. find 메서드도 콜백 함수를 호출하면서 3개의 인수를 전달한다.( item, index, arr)

const arr = ['banana', 'apple', 'orange','banana'];

arr.find((item) => item === 'banana'); // banana

9. Array.prototype.findIndex ES6

find 메서드와 똑같이 동작하지만 findIndex는 인덱스 값을 반환한다.

const arr = ['banana', 'apple', 'orange','banana'];

arr.findIndex((item) => item === 'banana'); // 0
10. Array.prototype.flatMap  ES10 
flatMap 메서드는 map + flat(1)

const arr = ['banana', 'orange'];

arr.map(x => x.split('')); // [['b', 'a', 'n', 'a', 'n', 'a'],['o', 'r', 'a', 'n', 'g', 'e']]
arr.map(x => x.split('')).flat(); // ['b', 'a', 'n', 'a', 'n', 'a', 'o', 'r', 'a', 'n', 'g', 'e']
arr.flatMap(x => x.split('')); // ['b', 'a', 'n', 'a', 'n', 'a', 'o', 'r', 'a', 'n', 'g', 'e']

0개의 댓글