Javascript/etc

[ Javascript ] - map과 filter 응용

algml0703 2022. 9. 20. 23:05
반응형

map과 filter 응용

map

map은 기본적으로 배열의 내장 함수로 존재하여 아래와 같이 작동할 수 있다.

<script>
  const log = console.log;

  log([1, 2, 3].map((a) => a + 1));
  // [2, 3, 4]
  
</script>

그런데 아래의 코드를 실행하면 에러가 발생하여 실행되지 않는데, 이는 querySelectorAll()로 생성된 것은 배열이 아닌 이터레이터객체이기 때문이다. 그렇기 때문에 배열의 내장함수인 map이 존재하지 않아 에러가 발생한다.


log(document.querySelectorAll("*").map((e) => a + 1));

이런 경우 아래의 코드와 같이 for of를 사용하여 직접 map 함수를 만들어 사용할 수 있다.

const map = (f, products) => {
  let names = [];
  for (const a of products) {
    names.push(f(a));
  }
  return names;
};

위의 코드를 보면 map함수를 첫번째 인자로 함수를 받아 반환되는 값의 형식을 설정해주고 있으며, 두번째 인자로 이터레이터 객체를 받아 작업을 실행시킨다.

사용자 함수인 map으로 위에서 에러가 난 부분에 적용해보면 아래와 같다.

<script>
  const log = console.log;

  const map = (f, products) => {
    let names = [];
    for (const a of products) {
      names.push(f(a));
    }
    return names;
  };

  log(map((el) => el.nodeName, document.querySelectorAll("*")));
  // ['HTML', 'HEAD', 'SCRIPT']
  const it = document.querySelectorAll("*")[Symbol.iterator]();
  log(it.next()); // {value: html, done: false}
  log(it.next()); // {value: head, done: false}
  log(it.next()); // {value: script, done: false}

  // 제너레이터 함수로 이터레이터 객체를 만들어 map에 적용한 예시
  function* gen() {
    yield 2;
    yield 3;
    yield 4;
  }
  log(map((e) => e * e, gen()));
</script>

filter

이터레이터 객체를 받아 처리하는 filter 함수 예시

const log = console.log;

const products = [
  { name: "반팔티", price: 15000 },
  { name: "긴팔티", price: 20000 },
  { name: "핸드폰케이스", price: 15000 },
  { name: "후드티", price: 30000 },
  { name: "바지", price: 25000 },
];

let under20000 = [];
// 상품의 가격이 20000원 미만의 상품 filter
for (const a of products) {
  if (a.price < 20000) under20000.push(a);
}
log(under20000);

// 특정 가격 미만의 상품만 반환하도록 하는 filter 함수
const priceFilter = (price, iter) => {
  let underPrice = [];
  for (const a of iter) {
    if (a.price < price) underPrice.push(a);
  }
  return underPrice;
};

// 특정 가격 미만의 상품만 반환하도록 하는 filter 함수로써, 반환값에 대한 설정도 추가되었다.
const itemFilter = (fun, returnFun, iter) => {
  let filterItem = [];
  for (const a of iter) {
    if (fun(a)) filterItem.push(returnFun(a));
  }
  return filterItem;
};

log(priceFilter(20000, products));
log(
  itemFilter(
    (a) => {
      if (a.name.length < 4) return true;
      else return false;
    },
    (a) => a.name,
    products
  )
);

log(
  itemFilter(
    (a) => {
      if (a.name.length < 4) return true;
      else return false;
    },
    (a) => a.price,
    products
  )
);

 

[ 출처 ]

https://www.inflearn.com/course/functional-es6

반응형