filter와 find 메소드는 forEach와 map 메소드 처럼
배열에 요소들을 하나씩 살펴보면서 반복적인 동작을 하는 메소드이다.
아래 코드는 간단하게 게임 캐릭터 정보를 담고 있는 객체들을 배열로 묶어서
"BossGroup"변수를 생성하였다.
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
filter 메소드
"filter" 메소드를 활용하면 원하는 조건에 맞는 요소들만 추려내서 새로운 배열을 만들 수 있다.
// filter와 find
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "다크나이트", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
const types = BossGroup.filter((el) => el.type === "마법사");
console.log(types);
뭔가 map 메소드와 비슷해 보이는데
실제로도 아규먼트가 되는 콜백 함수의 구조가 map 메소드와 비슷하다.
한가지 차이점은 리턴문으로 어떤 값을 전달하는 게 아니라
true 혹은 false로 평가되는 조건식을 리턴해준다.
즉, 메소드를 호출한 배열을 반복하면서
콜백함수가 리턴하는 조건식이 true가 되는 요소만 모아서 새로운 배열을 리턴해주는 것이다.
코드 내의 콜백 함수가 리턴하는 조건식을 보면
요소의 type 프로퍼티가 "마법사"인 요소만 추려내고있다.
실행하면 요소가 세 개인 배열이 출력되고
type이 "마법사"인 요소만 담겨있는 것을 확인할 수 있다.
메소드 이름 그대로 어떤 조건에 따라 필터링된 새로운 배열을 얻고자 할 때
유용하게 활용될 수 있다.(어떻게 보면 엑셀의 데이터 셀 - 필터링과 매우 유사하다)
그런데 filter 메소드는 항상 리턴값이 배열이기 때문에
아래와 같이 고유한 값을 활용 (job 프로퍼티) 해서
하나만 있는 요소를 필터링 하더라도
결국에는 하나의 요소를 가진 배열을 리턴해주게된다.
// filter와 find
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "다크나이트", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
const jobs = BossGroup.filter((el) => el.job === "바이퍼")
console.log(jobs);
물론 어떻게 보면 당연한 것 이긴 하지만
아래와 같이 spread구문을 활용해서 배열을 벗겨내는 작업을 해야 한다.
console.log(...jobs);
만약 지금처럼 여러 값들 중에서 유일한 하나의 값만 찾고자 할 때에는
filter가 아닌 find 메소드를 활용한다.
find 메소드
// filter와 find
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "다크나이트", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
const types = BossGroup.filter((el) => el.type === "마법사");
console.log(types);
// const jobs = BossGroup.filter((el) => el.job === "바이퍼")
// console.log(...jobs);
const jobs = BossGroup.find((el) => el.job === "바이퍼") // find 메소드
console.log(jobs);
filter에서 find 메소드로 바꾸고 spread 구문을 지우면
실행 결과는 filter로 spread 구문 사용한 것과 똑같이
유일한 하나의 값을 찾을 수 있다.
위와 같이 메소드 이름만 살짝 바꿔줘도 될만큼
filter와 find가 동작하는 방식은 서로 비슷하지만
명확하게 구분해야 할 차이점이 있다.
filter 와 find 차이점
①. filter는 리턴값이 배열이고 fined는 값이다.
(이 부분은 위에서 설명했으니 패스)
②. 같은 배열에서 메소드를 호출하더라도 각 메소드에 따라
반복하는 횟수가 달라질 수도 있다.
find 메소드 같은 경우에는 조건을 만족하는 하나의 값만 찾기 때문에
그 값을 찾는 순간 반복이 종료된다.
코드를 보면
// filter와 find
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "다크나이트", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
const jobs = BossGroup.find((el) => el.type === "해적")
console.log(jobs);
find 메소드로 배열 안에 tpye이 똑같이 "해적"인 요소를 찾는다면
type의 인덱스 위치가 좀 더 앞에 있는 요소를 먼저 리턴하고 find 메소드는 종료된다.
좀 더 설명하기 위해 아래의 코드로 수정해보자면
// filter와 find
const BossGroup = [
{ name: "행섭", job: "비숍", type: "마법사" },
{ name: "양천", job: "캐논마스터", type: "해적" },
{ name: "스기따라", job: "배틀메이지", type: "마법사" },
{ name: "힝카인", job: "카인", type: "궁수" },
{ name: "귀여운적혈구", job: "다크나이트", type: "전사" },
{ name: "저섭", job: "바이퍼", type: "해적" },
{ name: "찌듕", job: "아크메이지:불독", type: "마법사" },
{ name: "넌적혈구", job: "아델", type: "전사" },
{ name: "메르미르시츄", job: "메르세데스", type: "궁수" },
];
const types = BossGroup.filter((el, i)=> {
console.log(i);
return el.type === '마법사'
});
console.log(types);
const jobs = BossGroup.find((el, i)=>{
console.log(i);
return el.job === '배틀메이지';
})
console.log(jobs);
filter 메소드는 조건을 만족하는 모든 값을 모아야 하기 때문에
배열의 모든 인덱스가 콘솔에 출력될 것이고
find 메소드는 조건을 만족하는 하나의 요소만 찾으면 되니까
단 세 번의 인덱스만 콘솔에 출력될 것이다.
그말은 즉 find 메소드의 "콜백 함수가 세 번만 실행되고 종료되었다" 라고 볼 수 있다.
하지만 상황에 따라서 존재하지 않는 요소를 찾는다거나
혹은 가장 마지막에 위치해있는 요소를 찾는다면
결국 filter메소드와 find 메소의 반복 횟수가 같아질 수는 있을 것이다.
아무튼 "반복 횟수가 달라질 수도 있다" 라는 것은
"프로그램의 효율 측면에서도 중요한 내용이다." 라는 것을 말하고 싶은 것이다.
그리고 굳이 설명안해도 알겠지만
find 메소드에서 존재하지 않는 요소를 찾으려고하면
당연히 undefined 값이 출력될 것이다.
▶ Notion
https://purrfect-gargoyle-935.notion.site/find-159e9530b3e1807e8abfd3cc931b22d3?pvs=4
https://purrfect-gargoyle-935.notion.site/filter-159e9530b3e1803ab7f5d737783768ec?pvs=4
'JS' 카테고리의 다른 글
(27) Modern JavaScript - 배열 메소드 : reduce (0) | 2024.12.12 |
---|---|
(26) Modern JavaScript - 배열 메소드 : some, every (0) | 2024.12.11 |
(24) Modern JavaScript - 배열 메소드 : forEach, map (0) | 2024.12.10 |
모던 자바스크립트 (15) ~ (23) 정리 (0) | 2024.12.09 |
(23) Modern JavaScript - try...catch 문 (0) | 2024.12.09 |