이번에는 mapfilter에 대해 알아보자.


map

map은 배열을 순회하면서 각 요소를 변환하고 새 배열을 만든다
👉❗그러니까, map은 항상 같은 길이의 새 배열을 반환한다.

  • 예시
const numbers = [1, 2, 3];

const result = numbers.map(n => n * 10);

console.log(result);   // [10, 20, 30]
console.log(numbers);  // [1, 2, 3]

여기서 중요한 포인트는

numbers.map(n => n * 10)

이 코드의 의미는 [10, 20, 30]의 새 배열을 만드는 것이다.

return중요성
새 배열을 반환하는 것인데, return이 없으면[undefined]를 선언해버린다.


filter

filter는 조건에 맞는 요소만 남겨서 새 배열을 만든다.

👉 map과 다른 점은 배열의 길이가 바뀔 수 있다는 점이다.

  • 예시
const numbers = [1,2,3,4,5];

const result = numbers.filter(n => n > 3);

console.log(result); // [4,5]

map vs filter

메서드역할결과 배열 길이
map요소를 변환항상 동일
filter요소를 선별줄어들 수 있음

실습예제

  • map
const students = [
  {
    name: "홍길동",
    age: 20,
    gender: "male",
    hobbies: ["reading", "coding", "exercise"],
  },
  {
    name: "이영희",
    age: 21,
    gender: "female",
    hobbies: ["reading", "coding", "yoga"],
  },
  { name: "김철수", age: 22, gender: "male", hobbies: ["reading", "coding"] },
];

TODO : 위 배열에서 이름과 취미 개수만 포함된 새로운 배열을 만들어 보세요.

const result = students.map(function (student) {
  return {
    name: student.name,
    hobbyCount: student.hobbies.length,
  };
});

result :

[
  { name: "홍길동", hobbyCount: 3 },
  { name: "이영희", hobbyCount: 3 },
  { name: "김철수", hobbyCount: 2 }
]

  • filter
const students = [
  { name: "김철수", score: 45 },
  { name: "이영희", score: 82 },
  { name: "박민준", score: 91 },
  { name: "최수진", score: 60 },
  { name: "정도현", score: 73 },
];

TODO : 위 배열에서 70점 이상인 학생만 추출하세요.

const result = students.filter(function (student) {
  return student.score >= 70;
});

result :

[
  { name: "이영희", score: 82 },
  { name: "박민준", score: 91 },
  { name: "정도현", score: 73 }
]

  • map + filter
const students = [
  { name: "김철수", score: 45 },
  { name: "이영희", score: 82 },
  { name: "박민준", score: 91 },
  { name: "최수진", score: 60 },
  { name: "정도현", score: 73 },
];

TODO : 위 배열에서 70점 이상인 학생의 이름만 배열로 만들어 보세요.

const result = students
  .filter(function (student) {
    return student.score >= 70;
  })
  .map(function (student) {
    return student.name;
  });

result :

["이영희", "박민준", "정도현"]

📌 filter + map과 같은 구조에서는 .으로 이어서 쓴다

const newEx = example.filter(function (e) {
  //
  }).map(function (e) {
    //
  });

todo list 만들어보기

// 아래 6개의 함수를 완성하세요.

let todos = [];
let nextId = 1;

// 1. 할 일 추가
function addTodo(title) {}

// 2. 할 일 목록 조회
function getTodos() {}

// 3. 할 일 완료 토글
function toggleTodo(id) {}

// 4. 할 일 삭제
function deleteTodo(id) {}

// 5. 제목 수정
function updateTodo(id, newTitle) {}

// 6. 완료된 항목만 반환
function getCompletedTodos() {}

// --- 실행 테스트 ---
addTodo("JS 공부하기");
addTodo("운동하기");
addTodo("책 읽기");

toggleTodo(1);
toggleTodo(3);

console.log(getTodos());
// id 1, 3번 done: true / id 2번 done: false

console.log(getCompletedTodos());
// [{ id: 1, ... }, { id: 3, ... }] 만 나와야 함

updateTodo(2, "수영하기");
deleteTodo(1);

console.log(getTodos());
console.log(getCompletedTodos()); // id 3번만 남아야 함

하나씩 해결해보자

1️⃣ 할 일 추가

💡 생각
: todos 라는 빈 배열에 id, title, done 세 가지를 넣어야하니, 새 배열을 만들어서 push해보자.
💻 코드

function addTodo(title) {
  newTodo = {
    id: nextId++,
    title: title,
    done: false,
  };

  todos.push(newTodo);
}

2️⃣ 할 일 목록 조회

💡 생각
: 처음에는 감이 안잡혔지만 간단하게 생각해보니 그냥 리스트만 return하면 되는 거였다.

💻 코드

function getTodos() {
  return todos;
}

3️⃣ 할 일 완료하면 true로 변경하는 토글

💡 생각
: 기본값이 다 done: false로 되어있으니, 이걸 true로 바꿔주면 된다.
다른 배열도 다 같으니 map사용, 그리고 펼쳐내서 done: 값만 바꿔줘보자

💻 코드

function toggleTodo(id) {
  const td = todos.map(function (todo) {
    if (todo.id === id) {
      return { ...todo, done: !todo.done };
    } else {
      return todo;
    }
  });

  todos = td;
}

4️⃣ 할 일 삭제

💡 생각
: id를 받아오니 삭제할 id와 같은 id를 제외하고 → 받아온 id와 다른 id를 반환
즉, id가 같은 것을 제외하면 된다.
filter를 사용해서 같은 id를 뺀 새 배열을 만들고 그걸 todos에 넣자.

💻 코드

function deleteTodo(id) {
  const dt = todos.filter(function (d) {
    return d.id !== id;
  });

  todos = dt;
}

5️⃣ 제목 수정

💡 생각
: 같은 id의 title를 변경해주면 된다. 역시 배열이 같고, title만 변경해주면 되니 map을 사용해서 같으면 title을 변경, 아니면 그대로 return하자.

💻 코드

function updateTodo(id, newTitle) {
  todos = todos.map(function (u) {
    if (u.id === id) {
      return { ...u, title: newTitle };
    } else {
      return u;
    }
  });
}

6️⃣ 완료된 항목만 반환

💡 생각
: done: true인 것만 찾아내서 return하면 된다. filter를 사용해서 done: true를 찾아내 담은 새 배열을 만들어 return하자.

💻 코드

function getCompletedTodos() {
const cd = todos.filter(function (c) {
return c.done === true;
});

return cd;
}


📌 최종 정리 코드

// 아래 6개의 함수를 완성하세요.

let todos = [];
let nextId = 1;

// 1. 할 일 추가
function addTodo(title) {
  newTodo = {
    id: nextId++,
    title: title,
    done: false,
  };

  todos.push(newTodo);
}

// 2. 할 일 목록 조회
function getTodos() {
  return todos;
}

// 3. 할 일 완료 토글
function toggleTodo(id) {
  const td = todos.map(function (todo) {
    if (todo.id === id) {
      return { ...todo, done: !todo.done };
    } else {
      return todo;
    }
  });

  todos = td;
}

// 4. 할 일 삭제
function deleteTodo(id) {
  const dt = todos.filter(function (d) {
    return d.id !== id; //
  });

  todos = dt;
}

// 5. 제목 수정
function updateTodo(id, newTitle) {
  return todos.map(function (u) {
    if (u.id === id) {
      return { ...u, title: newTitle };
    } else {
      return u;
    }
  });
}

// 6. 완료된 항목만 반환
function getCompletedTodos() {
  const cd = todos.filter(function (c) {
    return c.done === true;
  });

  return cd;
}

// --- 실행 테스트 ---
addTodo("JS 공부하기");
addTodo("운동하기");
addTodo("책 읽기");

toggleTodo(1);
toggleTodo(3);

console.log(getTodos());
// id 1, 3번 done: true / id 2번 done: false

console.log(getCompletedTodos());
// [{ id: 1, ... }, { id: 3, ... }] 만 나와야 함

updateTodo(2, "수영하기");
deleteTodo(1);

console.log(getTodos());
console.log(getCompletedTodos()); // id 3번만 남아야 함
profile
다른 건 노력의 시간

0개의 댓글