파트4. map filter reduce - ChoDragon9/posts GitHub Wiki

map

const map = (iteratee, iterable) => {
  const res = [];
  for (const a of iterable) {
    res.push(iteratee(a));
  }
  return res;
}
map(v => v.name, [{name: 'a'}, {name: 'b'}]);

이터러블 프로토콜을 따른 map의 다형성

NodeList는 Iterable이기 때문에 map 함수를 사용할 수 있습니다.

map(elem => elem.nodeName, document.querySelectorAll('*'));

function *gen() {
  yield 1;
  yield 2;
  yield 3;
}
map(v => console.log(v), gen())

filter

const filter = (predicate, iterable) => {
  const res = [];
  for (const a of iterable) {
    if (predicate(a)) res.push(a);
  }
  return res;
}
filter(v => v > 3, [1, 2, 3, 4, 5]);
// output : [4, 5]

reduce

const reduce = (reducer, accumulator, iterable) => {
  for (const a of iterable) {
    accumulator = reducer(accumulator, a);
  }
  return accumulator;
}

const add = (a, b) => a + b;
console.log(reduce(add, 0, [1, 2, 3, 4]));
// output : 10

초기값이 없어도 동작하도록 수정한 코드입니다.

const reduce = (reducer, accumulator, iterable) => {
  if (!iterable) {
    iterable = accumulator[Symbol.iterator]();
    accumulator = iterable.next().value;
  }
  for (const a of iterable) {
    accumulator = reducer(accumulator, a);
  }
  return accumulator;
}

const add = (a, b) => a + b;
console.log(reduce(add, 0, [1, 2, 3, 4]));
// output : 10

map+filter+reduce

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

console.log(
  reduce(
    (acc, price) => acc + price,
    map(
      p => p.price,
      filter(p => p.price < 20000, products)
    )
  )
);
// output : 30000