[Scala] fold, map, filter

smlee·2023년 8월 7일
0

Scala

목록 보기
3/37
post-thumbnail

Scala에서는 반복문 대신 사용할 수 있는 다양한 메서드를 지원한다. 대표적으로 foldLeft, map, filter 등이 그 예이다. 이 각각의 메서드를 알아보려고 한다.

1. fold

foldLeft와 foldRight를 알기 전에 먼저 fold를 알아놓는게 좋다.

(1) fold

Fold는 주어진 결합 함수(Combining Operation)를 데이터 구조에 대해 재귀적으로 호출하여 결과값을 만들어내는 고계 함수(higher-order function)이다.

fold는 재귀적으로 prefix를 삽입하는 방식이다.

fold를 f로 표현하면 다음과 같다.

만약 [1,2,3]인 경우, fold는 다음과 같이 진행된다.

  1. 빈 리스트 []와 prefix 3이 존재한다 => 두 개를 결합하여 새로운 List인 [3]이 된다.
  2. 1번 과정의 결과인 [3]과 prefix 2가 존재한다 => 두 개를 결합하여 새로운 리스트 [2, 3]이 된다.
  3. 2번 과정의 결과인 [2, 3]과 prefix 1이 존재한다 => 두 개를 결합하여 새로운 리스트 [1,2,3]이 된다.

이를 함수로 나타내면 result_list = f(1, f(2, f(3, nil)))이 되는 것이다.

(2) foldLeft? foldRight?

그렇다면 foldLeft와 foldRight는 무엇일까. 이 두 가지 메소드를 나누는 기준은 fold의 방향이다. 말로 표현하면 이해하기 힘드니 식으로 나타내면 다음과 같다.

a) foldLeft

f(f(f(f(1, 2),3) 4), 5) => 마지막 요소를 제외한 요소들을 재귀적으로 처리한다. 그리고, 마지막 요소와 결합한다.

b) foldRight

f(1,f(2, f(3, f(4,5)))) => 첫 번째 요소를 제외한 요소들을 재귀적으로 처리한다. 그리고, 첫번째 요소와 결합한다.

사용법

리스트명.foldLeft/foldRight(최초 값){
	(최초값 변수, 리스트/배열 내부 원소) => {
    	//operations
    }
}

가장 바깥 좌측에는 리스트(배열)명을 적어준다. 즉, 어느 리스트(배열)에서 실행할지를 명시해주는 것이다.

그 후 foldLeft를 사용할 것인지 foldRight를 사용할 것인지 정하고, 최초의 값을 넣는다. 예를 들어, 리스트 안의 모든 원소들의 합을 구하는 것이면 최초값인 0을 넣는다.

그리고 중괄호를 열어 연산을 시작한다. 그리고, 2개의 인자가 들어온다. 앞의 인자를 최초값 변수이며, 두번째 원소는 내부 원소가 들어온다. 그리고 중괄호 안에 실행할 함수를 넣어주면 된다.


def add(x:Int, y:Int):Int = x+y

number_list.foldLeft(0){
	(sum, number) => add(sum, number)
}

이 코드는 리스트 내부의 모든 원소들의 합을 구하는 코드이다. 합을 구하기 위해서 최초 변수는 0부터 시작해야하므로 foldLeft 내부 소괄호에는 0이 들어갔다. 그리고, 0으로 초기화된 변수명을 sum으로 짓고, number를 더해줬다. 즉, sum에 리스트 값들을 하나씩 더해주는 연산인 것이다.

filter

filter는 리스트나 함수 내부에서 소괄호 내부의 조건을 만족하는 것들만 뽑는 것이다.

리스트명.filter(x=>필터링 조건)

이때, 위의 x값 대신 원소를 가리킬 다른 단어를 사용해도 된다.


위의 evenNumberList는 numberList에서 짝수인 원소만 뽑아 새로운 리스트를 만든 것이다. 짝수를 필터링하기 위해서는 2로 나눈 나머지가 0이 되어야 한다. 따라서 필터링 조건을 걸어주었다.

만약 3이상인 수를 필터링하고 싶으면 어떻게 할까?

val moreThanThree = numberList.filter(x=>x>=3)

조건문을 바꾸어 필터링 조건만 바꾸어주면 새로운 리스트(배열)가 생성된다.

map

map 역시 리스트(배열)의 모든 원소를 순회하는 메서드이다.

리스트명.map(원소명 => 연산)

filter와 비슷한 형태로 사용한다. 모든 원소에 대해 적용할 메서드나 연산을 넣어주면 된다.

다음 예시는 numberList의 모든 원소에 대하여 2배 해주는 연산이다.
map을 사용하여 모든 원소에 적용할 연산을 실행하여 제대로 결과값을 도출하는 것을 알 수 있다.

📚 Reference

foldLeft, map and filter in Scala

0개의 댓글