TIL 15일차

ᄋᄋ·2021년 12월 12일
0

출처: MDN

새로 알게 된 유용한 배열 메소드

Array.prototype.flat()

flat() 메서드는 모든 하위 배열 요소를 지정한 깊이까지 재귀적으로 이어붙인 새로운 배열을 생성함.

const newArr = arr.flat([depth])

매개변수 depth (Optional)
: 중첩 배열 구조를 평탄화할 때 사용할 깊이 값. 기본값은 1.

반환 값 : 하위 배열을 이어붙인 새로운 배열.
  • 중첩 배열 평탄화
const arr1 = [1, 2, [3, 4]];
arr1.flat();		// [1, 2, 3, 4]


const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();		// [1, 2, 3, 4, [5, 6]]


const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);		// [1, 2, 3, 4, 5, 6]


const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);		// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 배열 구멍 제거 : flat 메서드는 배열의 구멍도 제거함.
const arr5 = [1, 2, , 4, 5];
arr5.flat();		// [1, 2, 4, 5]
  • 대안 : reduce와 concat
const arr = [1, 2, [3, 4]];

// To flat single level array
arr.flat();

// is equivalent to
arr.reduce((acc, val) => acc.concat(val), []);
// [1, 2, 3, 4]

// or with decomposition syntax
const flattened = arr => [].concat(...arr);

고차함수

일급 객체(first-class citizen)의 세 가지 특징

대표적인 일급 객체 중 하나가 함수임.

  • 변수에 할당(assignment) 할 수 있다.
  • 다른 함수의 인자(argument)로 전달될 수 있다. (콜백함수)
  • 다른 함수의 결과로서 리턴될 수 있다.
    => 문자열, 숫자 같은 다른 데이터처럼 사용 가능!

고차 함수(higher-order function)

함수를 인자(argument)로 받을 수 있고, 함수의 형태로 리턴할 수 있는 함수.

다른 함수(caller)의 인자(argument)로 전달되는 함수를 콜백 함수(callback function)라고 함.
콜백 함수를 전달받은 고차 함수는, 함수 내부에서 이 콜백 함수를 호출(invoke) 할 수 있음. caller는 조건에 따라 콜백 함수의 실행 여부를 결정할 수 있음.

'함수를 리턴하는 함수'를 고안해 낸 논리학자 하스켈 커리(Haskell Curry)의 이름을 따, 커리 함수라고 함. 그러나 정확하게 구분하자면, 고차 함수가 커리 함수를 포함함.

- 다른 함수를 인자로 받는 경우

function double(num) {
  return num * 2;
}

function doubleNum(func, num) {
  return func(num);
}

let output = doubleNum(double, 4);
console.log(output);    // -> 8

- 함수를 리턴하는 경우

function adder(added) {
  return function (num) {
    return num + added;
  };
}

let output = adder(5)(3);    // -> 8
console.log(output);    // -> 8

const add3 = adder(3);
output = add3(2);
console.log(output);    // -> 5

- 함수를 인자로 받고, 함수를 리턴하는 경우

function double(num) {
  return num * 2;
}

function doubleAdder(added, func) {
  const doubled = func(added);
  
  return function (num) {
    return num + doubled;
  };
}

doubleAdder(5, double)(3);    // -> 13

const addTwice3 = doubleAdder(3, double);
addTwice3(2);    // --> 8

메소드 : 객체에 들어있는 함수

그래서 arr.map === arr['map']임.
즉, 배열 내장 고차함수들을 쓴다는 건, 객체에 들어있는 함수를 가져다 쓰는 거임.

arr.prototype.map
이렇게 prototype이라는 속성을 통해 map 메소드를 사용하는 거임.


배열 내장 고차함수

: forEach, find, filter, map, reduce, sort, some, every 등

- filter

모든 배열의 요소 중에서 특정 조건을 만족하는 요소를 걸러내는 메소드.

Array.prototype.filter()

배열의 각 요소에 콜백함수를 적용시켰을 때, true를 리턴하는 요소들만 모은 새로운 배열을 리턴.

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

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

반환 값 - 테스트를 통과한 요소로 이루어진 새로운 배열. 어떤 요소도 테스트를 통과하지 못했으면 빈 배열을 반환함.

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]

- map

배열의 각 요소가 특정 논리(함수)에 의해 다른 요소로 지정(map) 됨.

Array.prototype.map()

배열의 각 요소에 콜백함수를 적용시킨 새로운 배열 리턴.

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

currentValue - 처리할 현재 요소.
index (Optional) - 처리할 현재 요소의 인덱스.
array (Optional) - map()을 호출한 배열.
thisArg (Optional) - callback을 실행할 때 this로 사용되는 값.

반환 값 - 배열의 각 요소에 대해 실행한 callback의 결과를 모은 새로운 배열.

var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
  return num * 2;
});
// doubles는 이제 [2, 8, 18]
// numbers는 그대로 [1, 4, 9]

- reduce

배열의 각 요소를 특정 방법(함수)에 따라 원하는 하나의 형태로 응축.(reduction)

Array.prototype.reduce()

배열의 각 요소를 콜백 함수에 맞게 하나로 응축시킨 값을 리턴.

arr.reduce(callback[, initialValue])

accumulator - 누산기는 콜백의 반환값을 누적함. 콜백의 이전 반환값 또는, 콜백의 첫 번째 호출이면서 initialValue를 제공한 경우에는 initialValue의 값임.

currentValue - 처리할 현재 요소.

currentIndex (Optional) - 처리할 현재 요소의 인덱스. initialValue를 제공한 경우 0, 아니면 1부터 시작함.

array (Optional) - reduce()를 호출한 배열.

initialValue (Optional) - callback의 최초 호출에서 첫 번째 인수에 제공하는 값. 초기값을 제공하지 않으면 배열의 첫 번째 요소를 사용함. 빈 배열에서 초기값 없이 reduce()를 호출하면 오류가 발생함.

반환 값 - 누적 계산의 결과 값.

[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
  return accumulator + currentValue;
});

[0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr );

[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array) {
  return accumulator + currentValue;
}, 10);

+)

Array.prototype.forEach()

: forEach() 메서드는 주어진 함수를 배열 요소 각각에 대해 실행함.

arr.forEach(callback(currentvalue[, index[, array]])[, thisArg])

currentValue - 처리할 현재 요소.
index (Optional) - 처리할 현재 요소의 인덱스.
array (Optional) - forEach()를 호출한 배열.
thisArg (Optional) - callback을 실행할 때 this로 사용할 값.

반환 값 - undefined.


Array.prototype.find()

: find() 메서드는 주어진 판별 함수를 만족하는 첫 번째 요소의 값을 반환. 그런 요소가 없다면 undefined를 반환. (filter와의 차이는 filter는 조건에 만족하는 요소 모두를 모아 리턴한다면, find는 조건에 만족하는 첫번째 값 하나만 리턴함.)

const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);
// expected output: 12

Array.prototype.sort()

sort() 메서드는 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환함. 정렬은 stable sort가 아닐 수 있음. 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따름.

arr.sort([compareFunction])
compareFunction Optional - 정렬 순서를 정의하는 함수. 생략하면 배열은 각 요소의 문자열 변환에 따라 각 문자의 유니 코드 코드 포인트 값에 따라 정렬됨.

반환 값 - 정렬한 배열. 원 배열이 정렬되는 것에 유의. 복사본이 만들어지는 것이 아님. (mutable)

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
앞글자가 알파벳 순서상 앞에 있는 순으로 배정됨. 만약 앞글자가 같다면 두번쨰 글자로 비교함.

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
맨 앞에 수가 작은 순으로 배정됨. 맨 앞 숫자가 같다면 다음 자리에서 비교함.

오름차순 - arr.sort((a, b) => a - b)
내림차순 - arr.sort((a, b) => b - a)

문자던 숫자던 오름차는 a-b, 내림차는 b-a를 기준으로 생각하면 됨.

오름차(a-b)는

a>b면 1을 리턴,
a<b면 -1을 리턴,
a=b면 0을 리턴.(문자 오름차,이게 기본값)

내림차(b-a)는

a>b면 -1을 리턴,
a<b면 1을 리턴,
a=b면 b-a는 0을 리턴.(문자 내림차)

<예시>

const arr = ['banana', 'b', 'boy'];
arr.sort(function(a, b) {
  if(a < b) return 1;	  // b > a인데 1을 리턴한다는 건 'b-a'(내림차)라는 거임.
  if(a > b) return -1;
  if(a === b) return 0;
});

// ['boy', 'banana', 'b']

대소문자 구분없이 정렬하려면,

<오름차순 예시>
const arr = ['banana', 'b', 'Boy'];

arr.sort(function(a, b) {
  const upperCaseA = a.toUpperCase();
  const upperCaseB = b.toUpperCase();
  
  if(upperCaseA > upperCaseB) return 1;
  if(upperCaseA < upperCaseB) return -1;
  if(upperCaseA === upperCaseB) return 0;
});
// ['b', 'banana', 'Boy']

+) sort() 함수로 객체 정렬

: 객체의 price값을 기준으로 오름차순 정렬하는 예시

const arr = [
  {name: 'banana', price: 3000}, 
  {name: 'apple', price: 1000},
  {name: 'orange', price: 500}
];

arr.sort(function(a, b) {
  return a.price - b.price;
});

// 결과
{"name":"orange","price":500}
{"name":"apple","price":1000}
{"name":"banana","price":3000}

참고: https://hianna.tistory.com/409


Array.prototype.some()

콜백함수의 조건에 만족하는 배열의 요소 하나라도 있으면 true, 아예 만족하는 요소가 없으면 false.

구문 : arr.some(callback[, thisArg])


Array.prototype.every()

배열 안의 모든 요소가 주어진 판별 함수의 조건에 만족하면 true, 만족하지 못하는 요소가 하나라도 있으면 false.


추상화(abstraction)

복잡한 어떤 것을 압축해서 핵심만 추출한 상태로 만드는 것.

추상화의 관점에서 함수를 바라보면, 함수는 사고(thought) 또는 논리(logic)의 묶음임. 함수를 통해 얻은 추상화를, 한 단계 더 높인 것이 고차 함수임.

함수 = 값을 전달받아 값을 리턴한다 = 값에 대한 복잡한 로직은 감추어져 있다 = 값 수준에서의 추상화

고차 함수는 이 추상화의 수준을 사고의 추상화 수준으로 끌어올림.

  • 값 수준의 추상화: 단순히 값(value)을 전달받아 처리하는 수준

  • 사고의 추상화: 함수(사고의 묶음)를 전달받아 처리하는 수준
    다시 말해 고차 함수를 통해, 보다 높은 수준(higher order)에서 생각할 수 있음.

고차함수 = 함수를 전달받거나 함수를 리턴한다 = 사고(함수)에 대한 복잡한 로직은 감추어져 있다 = 사고 수준에서의 추상화

추상화의 관점에서 고차 함수가 갖는 이점

: 추상화를 통한 생산성(productivity)의 향상(= 효율성 증대).

profile
개발자A

0개의 댓글