Array higher order function

shorry·2022년 2월 8일
0

JavaScript

목록 보기
7/9

✔️Array higher order function


  • 고차함수(Higher order function)는 함수를 인자로 전달받거나 함수를 결과로 반환하는 함수를 말한다.
  • 고차 함수는 외부 상태 변경이나 가변(mutable) 데이터를 피하고 불변성(Immutability)을 지향하는 함수형 프로그래밍에 기반을 두고 있다.
    • 함수형 프로그래밍
      • 순수 함수(Pure function)와 보조 함수의 조합을 통해 로직 내에 존재하는 조건문과 반복문을 제거하여 복잡성을 해결하고 변수의 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임이다.
      • 조건문이나 반복문은 로직의 흐름을 이해하기 어렵게 하여 가독성을 해치고, 변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있기 때문이다.
      • 함수를 통해 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 한 방법

📌1. Array.prototype.sort

  • Array.prototype.sort(compareFn?: (a: T, b: T) => number): this, ES1문법
  • 배열의 요소를 적절하게 정렬한다.
  • 기본 정렬 순서는 문자열 Unicode 코드 포인트 순서에 따른다.
  • this(원본배열) 을 변경한다.

    Array.prototype.sort 메서드는 10개 이상의 요소가 있는 배열을 정렬할 때 불안정한 알고리즘인 quicksort 알고리즘을 사용했다. 배열이 올바르게 정렬되도록 ECMAScript 2019는 Array.prototype.sort 메서드에 Timsort 알고리즘을 사용한다.

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

// ascending(오름차순)
fruits.sort();
console.log(fruits);  // ['apple', 'banana', 'orange']
// descending(내림차순)
fruits.reverse();
console.log(fruits);  // ['orange', 'banana', 'apple']
  • 기본 정렬 순서는 문자열 Unicode 코드 포인트 순서에 다른다. 배열의 요사가 숫자 타입이라 할지라도 배열의 요소를 일시적으로 문자열로 변환한 후, 정렬한다.
    • 그 결과, 숫자를 정렬하면, 예를들어 10이 2보다 앞에 오는 경우가 발생한다.
  • 이러한 경우, sort메서드의 인자로 정렬순서를 정의하는 비교 함수를 인수로 전달한다.
// 숫자를 정렬하는 경우,
const arr = [40, 100, 1, 5, 2, 25, 10]

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

Array including Object

const frontEnd = [
  { id: 4, content: 'React' },
  { id: 2, content: 'CSS' },
  { id: 3, content: 'JavaScript' },
  { id: 1, content: 'HTML' }
];

// 비교함수
function compare(key) {
  return function (a, b) {
    return a[key] > b[key] ? 1 : (a[key] < b[key] ? -1 : 0);
    // 프로퍼티 값이 문자열인 경우가 있으므로 비교 연산을 사용한다.
    // 문자열에 - 산술 연산을 사용하면 NaN이 값이 나오기 때문
  };
}

// id기준 정렬
frontEnd.sort(compare('id'));
// content기준 정렬
frontEnd.sort(compare('content'));

📌2. Array.prototype.forEach

  • Array.prototype.forEach(callback: (value: T, index: number, array: T[]) => void, thisArg?: any): void, ES5문법
  • forEach 메소드는 for 문 대신 사용할 수 있다.
  • 배열을 순회하며 배열의 각 요소에 대하여 인자로 주어진 콜백함수를 실행한다. 반환값은 undefined이다.
  • 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, forEach 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • forEach 메소드는 원본 배열(this)을 변경하지 않는다. 하지만 콜백 함수는 원본 배열(this)을 변경할 수는 있다.
  • forEach 메소드는 for 문과는 달리 break 문을 사용할 수 없다. 다시 말해, 배열의 모든 요소를 순회하며 중간에 순회를 중단할 수 없다.
  • for 문에 비해 성능이 좋지는 않다. 하지만 for 문보다 가독성이 좋으므로 적극 사용을 권장한다.
  • this(원본배열) 을 변경하지 않는다.
const arr = [1, 2, 3];
let result = [];

// 1. for 문
for (let i = 0; i < arr.length; i++) {
  result.push(arr[i] ** 2 );
  
// 2. forEach 메서드
arr.forEach(num => result.push(num ** 2));
  
console.log(result);  // [1, 4, 9]

📌3. Array.prototype.map

  • Array.prototype.map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[], ES5문법
  • 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백 함수의 반환값(결과값)으로 새로운 배열을 생성하여 반환한다.
  • 콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, map 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.
const numbers = [1, 4, 9];
const roots = numbers.map(Math.sqrt);
  
console.log(roots);  // [1, 2, 3]
console.log(numbers);  // [1, 4, 9]

forEach vs map

  • forEach 메소드는 배열을 순회하며 요소 값을 참조하여 무언가를 하기 위한 함수이며 map 메소드는 배열을 순회하며 요소 값을 다른 값으로 맵핑하기 위한 함수이다.

📌4. Array.prototype.filter

  • Array.prototype.filter(callback: (value: T, index: number, array: Array) => any, thisArg?: any): T[], ES5문법
  • filter 메소드를 사용하면 if 문을 대체할 수 있다.
  • 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수의 실행 결과가 true인 배열 요소의 값만을 추출한 새로운 배열을 반환한다.
  • 배열에서 특정 케이스만 필터링 조건으로 추출하여 새로운 배열을 만들고 싶을 때 사용한다.
    -콜백 함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, filter 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.
const result = [1, 2, 3, 4, 5].filter(num => num % 2 == 1);
console.log(result);  // [1, 3, 5]

📌5. Array.prototype.reduce

  • Array.prototype.reduce<U>(callback: (state: U, element: T, index: number, array: T[]) => U, firstState?: U): U, ES5문법
  • 배열을 순회하며 각 요소에 대하여 이전의 콜백함수 실행 반환값을 전달하여 콜백함수를 실행하고 그 결과를 반환한다.
  • this(원본배열) 을 변경하지 않는다.
const arr = [1, 2, 3, 4, 5];
const sum = sum.reduce((pre, cur) => pre + cur);
console.log(sum);  // 15

📌6. Array.prototype.some

  • Array.prototype.some(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): boolean, ES5문법
  • 배열 내 일부 요소가 콜백 함수의 테스트를 통과하는지 확인하여 그 결과를 boolean으로 반환한다.
  • 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.
const result1 = [2, 3 ,5 ,7 ,1].some(
  num => num > 10);
const result2 = ['apple', 'banana', 'mango'].some(
  item => item === 'banana');

console.log(result1);  // false
console.log(result2);  // true

📌7. Array.prototype.every

  • Array.prototype.every(callback: (value: T, index: number, array: Array) => boolean, thisArg?: any): boolean, ES5문법
  • 배열 내 모든 요소가 콜백함수의 테스트를 통과하는지 확인하여 그 결과를 boolean으로 반환한다.
  • 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.
const result1 = [21, 14, 35, 8, 79].every(
  num => num > 10);
const result2 = [21, 14, 35, 83, 79].every(
  num => num > 10);
  
console.log(result1);  // false
console.log(result2);  // true

📌8. Array.prototype.find

  • Array.prototype.find(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): T | undefined, ES6문법
  • Internet Explorer에서는 지원하지 않는다.
  • 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환한다.
    • 실행 결과가 참인 요소가 존재하지 않는 경우 : undefined 반환
  • 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.

filter vs find

  • filter는 콜백함수의 실행 결과가 true인 배열 요소의 값만을 추출한 새로운 배열을 반환한다. 따라서 filter의 반환값은 언제나 배열이다.
    하지만 find는 콜백함수를 실행하여 그 결과가 참인 첫번째 요소를 반환하므로 find의 결과값은 해당 요소값이다.
const users = [
  { id: 1, name: 'Lee' },
  { id: 2, name: 'Kim' },
  { id: 2, name: 'Choi' },
  { id: 3, name: 'Park' }
];

// find
let result = users.find(item => item.id === 2);
console.log(result); // { id: 2, name: 'Kim' }
// 요소값을 반환.

  
// filter
result = users.filter(item => item.id === 2);
console.log(result); // [ { id: 2, name: 'Kim' },{ id: 2, name: 'Choi' } ]
// 새로운 배열을 반환.

📌9. Array.prototype.findIndex

  • Array.prototype.findIndex(predicate: (value: T, index: number, obj: T[]) => boolean, thisArg?: any): number, ES6문법
  • Internet Explorer에서는 지원하지 않는다.
  • 배열을 순회하며 각 요소에 대하여 인자로 주어진 콜백함수를 실행하여 그 결과가 참인 첫번째 요소의 인덱스를 반환한다.
  • 콜백함수의 매개변수를 통해 배열 요소의 값, 요소 인덱스, 메소드를 호출한 배열, 즉 this를 전달 받을 수 있다.
  • this(원본배열) 을 변경하지 않는다.
const users = [
  { id: 1, name: 'Lee' },
  { id: 2, name: 'Kim' },
  { id: 2, name: 'Choi' },
  { id: 3, name: 'Park' }
];

// 콜백함수를 실행하여 그 결과가 참인 첫번째 요소의 인덱스를 반환한다.
function predicate(key, value) {
  return function (item) {
    return item[key] === value;
  };
}

// id가 2인 요소의 인덱스
let index = users.findIndex(predicate('id', 2));
console.log(index); // 1

// name이 'Park'인 요소의 인덱스
index = users.findIndex(predicate('name', 'Park'));
console.log(index); // 3

Reference



Word of the day

이제 OBJECT 공부하러 가야지~~??

End.

profile
I'm SHORRY about that

0개의 댓글