[JS] 내장 고차 함수 정리🧹 (filter, map...) + Set, Map

TATA·2023년 1월 12일
0

JavaScript

목록 보기
13/25

✔️ 고차 함수란?

함수를 리턴하는 함수이거나 함수를 전달인자로 받는 함수를 말한다.
함수의 전달인자로 전달되는 함수를 콜백함수라고 하고
함수를 리턴하는 함수를 커링함수하고 한다.

  • 고차 함수인 경우
function calculate(x, y){
	return function(){
		return x * y;
	}
}
// 함수를 리턴하고 있으므로 고차함수 입니다.
  • 고차 함수가 아닌 경우
function calcuate(x, y, z){
	const plus = function (num1, num2){
		return num1 + num2;
	}
	return plus(x, y) * z
}
// 함수를 전달인자로 받지 않고 있고
// 함수를 리턴하고 있지 않으므로 고차함수가 아닙니다.

✋ 잠깐! 일급객체는 뭔데?

1급객체, First Class Object

일급객체란 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다.

일급객체의 조건👇
"변수에 할당이 가능하다."
"다른 함수의 전달인자로 전달이 가능하다."
"다른 함수의 결과로서 리턴이 가능하다."

위 조건을 보면 함수데이터(string, number, boolean, array, object)
다루듯이 다룰 수 있다는 것을 알 수 있다.

따라서 함수가 일급객체이기에 고차함수로 활용이 가능하다는 것!


🧹 배열 내장 메서드

🧽 filter

배열의 각 요소 특정 논리(함수)에 따르면, 사실(true)일 때 따로 분류한다.

const words = ['elite', 'exuberant', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(result);
// ["exuberant", "destruction", "present"]

filter는 이렇게 조건에 맞는 데이터만 분류(filtering) 할 때 사용한다.

const menus  = ['americano', 'herb tea', 'earlgrey tea', 'hot choco']
const isTea = function (menu) {
  if (menu.includes('tea')) {
    return true
  }
}
let output = menus.filter(isTea);
console.log(output);
// [ 'herb tea', 'earlgrey tea' ]

🧽 map

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

const array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x * 2);

console.log(map1);
// Expected output: Array [2, 8, 18, 32]

map은 이렇게 하나의 데이터를 다른 데이터로 매핑 할 때 사용한다.

// 만화책 모음
const cartoons = [
  {
    id: 1,
    bookType: 'cartoon',
    title: '식객',
    subtitle: '어머니의 쌀',
    createdAt: '2003-09-09',
    genre: '요리',
    artist: '허영만',
    averageScore: 9.66,
  },
  {
    id: 2,
    // .. 이하 생략
  },
  // ... 이하 생략
]; 

// 만화책 한 권의 부제를 리턴하는 로직(함수)
const findSubtitle = function (cartoon) {
  return cartoon.subtitle;
}; 

// 각 책의 부제 모음 
const subtitles = cartoons.map(findSubtitle); // ['어머니의 쌀', ...]

콜백 함수에 두 번째 전달인자를 줄 경우 인덱스를 가져온다.

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

arr.map((el, idx) => `${idx}: ${el * 2}`)
// ['0: 2', '1: 4', '2: 6', '3: 8', '4: 10']
// ❗️참고) 웬만하면 사용하지 않는 것이 좋음

🧽 reduce

reduce는 이렇게 여러 데이터를, 하나의 데이터로 응축할 때 사용한다.

const sum = [1, 2, 3, 4];

const result = sum.reduce((total, current) => {
  return total + current;
}, 0); // 0은 total의 초기값이 0이라는 뜻이다.

console.log(result);
// 10

물론 문자열에서도 사용이 가능하다.

let output = getLongestElement(["one", "two", "three"]);

// 문자열을 요소로 갖는 배열을 입력받아 배열에서 가장 긴 문자열을 리턴
function getLongestElement(arr) {
  return arr.reduce((total, current) => {
    if (total.length >= current.length) return total;
    else return current;
  }, "");
}

console.log(output);
// three

🧽 forEach

forEach는 콜백함수의 배열에 있는 각 요소에 대해 오름차순으로 한 번씩 실행한다.

const array1 = ['a', 'b', 'c'];

array1.forEach(element => console.log(element));

// Expected output: "a"
// Expected output: "b"
// Expected output: "c"

값이 3개라면 2번째는 index, 3번째는 배열 객체를 뜻한다.

arr.forEach(func(value, index, array))
// value : 현재 순회 중인 요소
// index : 현재 순회 중인 요소의 index
// array : 배열 객체

🧽 find

find는 콜백함수의 반환 값이 true인 첫 번째 요소를 반환한다.

const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);

console.log(found);
// 12

🧽 findIndex

findIndex는 콜백함수의 반환 값이 true인 첫 번째 요소의 인덱스를 반환한다.

const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;

console.log(array1.findIndex(isLargeNumber));
// 3

🧽 some

some은 콜백함수의 반환값이 단 한 번이라도 참이면 true,
모두 거짓이라면 false를 반환한다.

const array = [1, 2, 3, 4, 5];
const even = (element) => element % 2 === 0;

console.log(array.some(even));
// true

🧽 every

every는 콜백함수의 반환값이 모두 참이면 true,
하나라도 거짓이면 false를 반환한다.

const isBelowThreshold = (currentValue) => currentValue < 40;

const array1 = [1, 30, 39, 29, 10, 13];

console.log(array1.every(isBelowThreshold));
// true

🧽 sort

sort는 요소들을 정렬(유니코드 순서대로)해준다.

const texts = ['aa', 'b', 'd', 'c']
texts.sort()
console.log(texts);
// ['aa', 'b', 'c', 'd']

const array1 = [1, 30, 21, 100000];
array1.sort();
console.log(array1);
// [1, 100000, 21, 30]
// ❗️참고) 숫자는 오름차순으로 정렬되지 않는다.

숫자를 오름차순으로 정리하고 싶다면?
sort() + 비교 함수를 추가해 줘야 한다.

숫자를 오름차순 하기

const nums = [1, 30, 21, 100000];
nums.sort((a, b) => a - b);
console.log(nums);
// [1, 21, 30, 100000]

숫자를 내림차순 하기

const nums = [1, 30, 21, 100000];
nums.sort((a, b) => b - a);
console.log(nums);
// [100000, 30, 21, 1]

🧽 filter + some

data 객체의 allGroup 배열에서 myGroup 배열에 속하지 않는 객체들만 필터링하여 filteredData 배열에 저장하는 코드

const data = {
  allGroup: [
    {
      groupId: 1,
      artistId: 1,
      groupName: 'BTS',
      groupImg: imgs.bts,
      grouplogoImg: imgs.btsPng,
    },
    {
      groupId: 2,
      artistId: 2,
      groupName: 'TXT',
      groupImg: imgs.txt,
      grouplogoImg: imgs.txtPng,
    },
    ....
    .....
    myGroup: [
    {
      groupId: 1,
      artistId: 1,
      groupName: 'BTS',
      groupImg: imgs.bts,
      grouplogoImg: imgs.btsPng,
    },
    {
      groupId: 2,
      artistId: 2,
      groupName: 'TXT',
      groupImg: imgs.txt,
      grouplogoImg: imgs.txtPng,
    },
  ],
};


// 시간복잡도는 O(n^2)
const filteredData = data.allGroup.filter((group) => {
  return !data.myGroup.some((myGroup) => myGroup.groupId === group.groupId);
});

-----

// 위와 같은 결과인 코드
// myGroup 배열의 길이에 상관없이 O(n)의 시간복잡도를 가지는 코드
const myGroupIds = new Set(data.myGroup.map((el) => el.groupId));

const filteredData = data.allGroup.filter((el) => {
  // myGroupIds에 현재 group의 groupId가 포함되어 있는지 확인하고
  // 포함되어 있지 않은 경우에만 true를 반환합니다.
  return !myGroupIds.has(el.groupId);
});

🧺 new Set(객체)

중복을 허용하지 않는다.

/*
* Set(중복제거) 객체의 주요 메서드
*
* add(value): 새로운 값을 추가합니다.
* delete(value): 주어진 값을 제거합니다.
* has(value): 주어진 값이 존재하는지 확인합니다.
* clear(): 모든 값을 제거합니다.
* size: Set 객체의 요소 개수를 반환합니다.
*
* new Set(array)를 사용하면 중복된 값이 제거된 배열을 반환 함
* const a = new Set([1, 1, 2])
* const b = [...a]
* console.log(b) // [1, 2] 출력 됨.
*/

/* ----- new Set 예시 ----- */

const mySet = new Set(); // Set 객체 생성

// add(value): 새로운 값을 추가합니다.
mySet.add(1);
mySet.add('hello');
mySet.add({ key: 'value' });
console.log(mySet); // Set { 1, 'hello', { key: 'value' } }

// delete(value): 주어진 값을 제거합니다.
mySet.delete('hello');
console.log(mySet); // Set { 1, { key: 'value' } }

// has(value): 주어진 값이 존재하는지 확인합니다.
console.log(mySet.has(1)); // true
console.log(mySet.has('hello')); // false

// clear(): 모든 값을 제거합니다.
mySet.clear();
console.log(mySet); // Set {}

// size: Set 객체의 요소 개수를 반환합니다.
console.log(mySet.size); // 0

🧺 new Map(객체)

key-value 형태의 자료형을 저장 가능하다.

/*
set(key, value): 특정 키에 값을 설정
get(key): 특정 키에 해당하는 값을 반환
has(key): 특정 키가 맵에 존재하는지 여부를 확인
delete(key): 특정 키와 해당하는 값을 맵에서 제거
clear(): 맵의 모든 요소를 제거
size: 맵의 요소 개수를 반환
keys(): 맵의 모든 키를 나타내는 이터레이터를 반환
values(): 맵의 모든 값들을 나타내는 이터레이터를 반환
entries(): 맵의 모든 엔트리(키-값 쌍)를 나타내는 이터레이터를 반환
forEach(callbackFn): 맵의 모든 요소에 대해 주어진 콜백 함수를 실행
*/

/* ----- new Map 예시 ----- */

// Map 객체 생성
const map = new Map();

// set(key, value) 메서드를 사용하여 값 추가
map.set('name', 'tata');

// get(key) 메서드를 사용하여 값 가져오기
console.log(map.get('name')); // tata

// has(key) 메서드를 사용하여 키의 존재 여부 확인
console.log(map.has('name')); // true

// delete(key) 메서드를 사용하여 요소 삭제
map.delete('name');

// size 속성을 사용하여 맵의 요소 개수 확인
console.log(map.size); // 1

// keys() 메서드를 사용하여 모든 키 가져오기
const keys = map.keys();
for (let key of keys) {
  console.log(key); // name
}


// values() 메서드를 사용하여 모든 값 가져오기
const values = map.values();
for (let value of values) {
  console.log(value); // tata
}

// entries() 메서드를 사용하여 모든 엔트리(키-값 쌍) 가져오기
const entries = map.entries();
for (let [key, value] of entries) {
  console.log(`${key}: ${value}`); // name: tata
}

// forEach(callbackFn) 메서드를 사용하여 모든 요소에 대해 콜백 함수 실행
map.forEach((value, key) => {
  console.log(`${key}: ${value}`); // name: tata
});



➕ WeakSet, WeakMap도 있음.

profile
🐾

0개의 댓글