Javascript - Array filter 사용법

이번에는 Javascript의 array가 가진 filter 함수의 정의와 사용법 더불어 활용법에 대해 이야기해보려고 합니다. array의 함수 중 가장 많이 쓰이는 함수 중 3 대장이라고 할 수 있는 것이 map, filter, reduce인데요. 그중 filter는 활용도가 높은 편이라 어디라고 정해진 곳 없이 사용되는 편입니다. 자 본격적으로 array의 filter 함수를 알아보러 가시죠.

filter 정의

Array.prototype.filter ( callbackfn [ , thisArg ] )

filter는 해석 그대로 걸러주는 역할을 하는 함수입니다. 주로 특정 조건을 만족하는 새로운 배열을 필요로 할 때 사용하는 편입니다. SQL로 치면 where절에서 하는 행위를 하는 함수입니다. ECMA에는 "주어진 배열의 값들을 오름차순으로 접근해 callbackfn을 통해 true를 반환하는 요소를 기준으로 신규 배열을 만들어 반환한다"라고 정의되어 있습니다. 예제를 통해 filter의 정의를 살펴보면 다음과 같습니다.

const numbers = [1, 2, 3, 4, 5];
const result = numbers.filter(number => number > 3);

console.log(numbers);
// [1, 2, 3, 4, 5];

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

예제 코드는 array를 통해 주어진 값들을 filter를 통해 3 보다 큰 수를 가진 값들을 걸러내는 방법입니다. 물론 for문을 사용해서도 이와 같은 작업을 할 수는 있지만 권장하지는 않습니다. map, filter, reduce와 같은 함수는 기본적으로 순차적으로 값을 접근한다라는 개념을 내포하고 있기 때문에 for문이 가진 순회를 별다른 코드를 작성하지 않고도 사용할 수 있게 해 주기 때문입니다.

const numbers = [1, 2, 3, 4, 5];
const result = [];

for (i = 0; i < numbers.length; i++) {
    const number = numbers[i];

    if (number > 3) {
        result.push(number);
    }
}

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

filter 사용법

filter를 사용하는 방법은 callbackfn을 통해 주어진 3개의 인자(요소 값, index, 순회하는 대상 객체)를 사용해 Boolean 값인 true 또는 false 값을 반환하는 함수를 등록하는 것입니다.

const numbers = [1];

numbers.filter((number, index, source) => {

    // number: 요소값
    // index: source에서 요소의 index
    // source: 순회하는 대상

    console.log(number);
    // 1

    console.log(index);
    // 0

    console.log(source);
    // [1]

    return number > 3;
});

filter을 사용하는 경우 주로 number에 해당하는 요소 값을 많이 활용하지만 index와 array도 함께 사용할 수 있습니다. filter 정의에서 다루었던 예제 코드보다는 조금 더 실무에서 많이 사용하는 방법을 보도록 하겠습니다.

const guys = [
    { name: 'YD', money: 500000 },
    { name: 'Bill', money: 400000 },
    { name: 'Andy', money: 300000 },
    { name: 'Roky', money: 200000 }
];

const rich = guys.filter(man => man.money > 300000);

console.log(rich);
// [{name: "YD", money: 500000}]

filter는 원시적인 값만 사용할 수 있는 것이 아니라, json과 같은 객체를 사용해 true를 판별할 수 있습니다. 즉 filter는 javascript에서 사용할 수 있는 모든 형태의 값을 참(true) 또는 거짓(false)으로 분류해 원하는 조건을 만족하는 새로운 배열을 반환할 수 있습니다.

 

filter는 filter 자체만으로도 쓰임새가 좋지만 다른 함수와의 조합성도 좋아 map, reduce와 같은 다른 함수와 함께 자주 쓰입니다. 예를 들어 위의 코드는 "300000 이상을 가진 사람들은?"이지만 map을 활용하면 "300000 이상을 가진 사람들의 이름은?"도 만들 수 있습니다.

const guys = [
    { name: 'YD', money: 500000 },
    { name: 'Bill', money: 400000 },
    { name: 'Andy', money: 300000 },
    { name: 'Roky', money: 200000 }
];

const richNames = guys.filter(man => man.money > 300000)
    .map(man => man.name)

console.log(richNames);
// ["YD", "Bill"]

filter는 일반적으로 조합을 이용해 사용하는 경우 강력한 힘을 발휘하는 함수 중 하나입니다.

 

filter를 사용하는 경우 알아두어야 주의사항이 몇 가지 있습니다.

 

- filter 함수는 객체를 직접 사용하거나 변형시키지 않지만 callbackfn을 통해 수정할 수 있으며 이는 문제를 발생시키는 원인이 됩니다.

- callbackfn이 호출되는 범위는 callbackfn이 처음 호출되기 이전이며, filter는 순회하는 도중에 추가된 요소는 접근하지 않습니다. 반대로 순회하는 도중 수정이 일어나면 변경된 값이 callbackfn에 전달되고 삭제된 요소는 접근하지 않습니다.

// array 요소가 추가되는 경우
const numbers = [1, 2, 3, 4, 5];

const result = numbers.filter(number => {
    numbers.push(number);
    return number > 3;
});

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

// array 요소가 수정되는 경우
const numbers = [1, 2, 3, 4, 5];

const result = numbers.filter(number => {
    numbers.pop();
    return number > 3;
});

console.log(result);
// [];

 

 

filter 활용법

- 다중 조건 사용하기

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

// 1보다 크고 5보다 작은 수를 찾는다
const newNumberes = numbers.filter(number => {
    if (number > 1 && number < 5) {
        return true;
    }
    
    return false;
});

console.log(newNumberes);
// [2, 3, 4]

const guys = [
    { name: 'YD', money: 500000 },
    { name: 'Bill', money: 400000 },
    { name: 'Andy', money: 300000 },
    { name: 'Roky', money: 200000 }
];

// money를 300000 이상 가진 name이 YD인 사람을 찾는다.
const rich = guys.filter(man => {
    if (man.money > 300000) {
        if (man.name === 'YD') {
            return true;
        }
    }

    return false;
});

console.log(rich);
// [{name: "YD", money: 500000}]

callbackfn에 등록하는 함수에는 boolean을 반환하기 위한 조건문은 1개 이상 정의할 수 있으며, 활용할 수 있는 값은 Javasript에서 사용이 가능한 모든 값입니다.

- 고차 함수 사용하기

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

// 3보다 큰 수 구하기
const graterThenThree = value => value > 3;

const newNumberes = numbers.filter(graterThenThree);

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

filter는 고차 함수를 사용해서 미리 정의한 식이나 정의되어 있는 식을 사용할 수 있습니다.

- 배열의 최고값(Max), 최소값(Min) 기준으로 분류하기

const guys = [
    { name: 'YD', money: 500000 },
    { name: 'Bill', money: 500000 },
    { name: 'Mark', money: 400000 },
    { name: 'Andy', money: 300000 },
    { name: 'Roky', money: 200000 },
    { name: 'Kan', money: 100000 },
    { name: 'Sam', money: 100000 }
];

const rich = guys.filter((man, index, target) => {
    const maxOfMoney = Math.max(...target.map(person => person.money));
    return man.money === maxOfMoney;
});

console.log(rich);
// [{name: "YD", money: 500000}, {name: "Bill", money: 500000}]

const poor = guys.filter((man, index, target) => {
    const minOfMoney = Math.min(...target.map(person => person.money));
    return man.money === minOfMoney;
});

console.log(poor);
// [{name: "Kan", money: 100000}, {name: "Sam", money: 100000}]

thisArg를 통해 전달받는 인자 중 순회하는 대상을 사용하면 많은 돈(Max) 또는 적은 돈(Min) 값을 식별할 수 있고 그 값을 필터의 판별 조건으로 사용하면 쉽게 많은 돈을 가진 사람이나 적은 돈을 가진 사람을 반환하는 기능을 만들어 볼 수 있습니다.

- 중복 제거하기

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

const newNumbers = numbers.filter((number, index, target) => {
    return target.indexOf(number) === index;
});

console.log(newNumbers);
// [1, 2, 3, 4, 5]

수정하지 않는 이상 순회하는 대상(target)은 변경되지 않는다는 속성을 이용해 filter와 indexOf를 조합하면 배열에 있는 중복을 제거 할 수 있습니다.

반응형

댓글

Designed by JB FACTORY