[C++] 입력된 원소들을 차례로 변환하는 std::transform

반응형

std::transform 기본 사용법

std::transform은 지정된 함수 객체를 입력된 범위의 모든 원소들에게 적용하고, 그 결과를 대상 범위에 출력하는 함수입니다.

이 함수를 사용하려면 먼저 다음 헤더를 포함해야 합니다.

#include <algorithm>

이 함수의 정의는 다음과 같습니다.

template<class InputIterator, class OutputIterator, class UnaryFunction>
OutputIterator transform(
    InputIterator first1,
    InputIterator last1,
    OutputIterator result,
    UnaryFunction func );

여기서, func는 입력된 범위의 원소를 인자로 전달로 받는 함수 객체입니다.
func 함수 객체는, UnaryFunction 이름이 말하듯이, 오직 1개의 매개 변수만을 가져야 합니다.

 

그리고, 이 transform 함수는 func 함수 객체가 반환한 값을 result가 가리키는 대상의 범위에 출력합니다.
이때, 대상의 범위는 입력된 원소들을 모두 담을 만큼 커야 합니다.
게다가, 대상 범위와 입력 범위가 일치해도 상관없습니다.
이 경우, 입력 원소의 값이 함수의 결과로 대체됩니다.

 

다음은 int 배열 원소들의 제곱을 계산하여 출력하는 예문입니다.

#include <iostream>
#include <algorithm>
using namespace std;

int compute( int v){	// 사용자 함수
    return v * v;
}

int main(){

    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int res[10];	// 출력 대상

    transform( arr, arr+ 10, res, compute);

    for( int v : res){	// 범위 기반 for
        cout << v << " ";
    }
}

▼출력

1 4 9 16 25 36 49 64 81 100

위 예제에서, compute 함수는 arr 배열로부터 값을 입력받아, 제곱 값을 계산한 후 반환합니다.

그리고, transform 함수는 이 반환값을 대상 배열 res에 출력합니다.

 

 

다음은 std::vector의 원소들의 값을 2 증가시키는 예문입니다.

여기에선, 람다 표현식( lamda expression )을 사용해서 적용할 함수를 손쉽게 구현했습니다.

int main(){

    vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    // 각 원소에 람다 표현식을 적용
    transform( vec.begin(), vec.end(), vec.begin(), [](int v)->int{ 
        return v + 2;
    } );

    for_each( vec.begin(), vec.end(), [](int v){
        cout << v << " ";
    } );
}

▼출력

3 4 5 6 7 8 9 10 11 12

이 함수에선 입력과 대상의 범위가 일치합니다.
이런 경우, 원본의 값이 함수가 적용된 값으로 변경됩니다.

 

그리고, 예문의 마지막 부분에서 std::for_each 함수를 사용해서 변경된 원소의 값들을 출력하고 있습니다.
for_each 함수도 입력된 범위의 모든 원소에 대하여 함수 객체를 적용하는 함수입니다.

 

[C++] 주어진 원소들에 함수를 적용하는 std::for_each

std::for_each 사용법std::for_each는 주어진 구간 내에 있는 원소들에 대하여 지정한 함수 객체를 적용하는 함수입니다. 이 함수를 사용하려면 다음의 헤더를 포함해야 합니다.#include 함수의 정의

codingbonfire.tistory.com

 

참고로, 이 for_each함수와 transform은 비슷하게 동작하지만, 분명히 구분되는 차이점 2가지가 있습니다.
첫 번째, transform은 함수가 적용된 결과를 대상 범위에 따로 출력할 수 있다는 것입니다.
for_each 함수는 그렇게 할 수 없습니다.

 

두 번째, transform은, 이제 설명할 것과 같이, 두 개의 입력 범위를 받아들일 수 있다는 것입니다.
for_each를 사용해서 이런 기능을 구현하기엔 불편한 점이 많이 있습니다.

 

 

std::transform의 두 번째 사용법

std::transform의 두 번째 정의는 다음과 같습니다.

template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction>
OutputIterator transform(
    InputIterator1 first1,
    InputIterator1 last1,
    InputIterator2 first2,
    OutputIterator result,
    BinaryFunction func );

이 버전의 특징은, 두 개의 입력 범위를 사용해서 결과를 출력할 수 있다는 것입니다.

( 이때, 두 번째 입력 범위의 원소수는 첫 번째 입력 범위의 원소수와 같거나 더 커야 합니다. )

여기서, func 함수 객체는, BinaryFunction 이름이 말하듯이, 두 개의 인자를 전달받을 수 있습니다.

그리고, 이 함수의 결과를 첫 번째 버전과 같이, 대상 범위 result에 저장합니다.

 

다음은 두 vector로부터 값들을 입력받아 합한 값을 출력하는 예문입니다.

int main(){

    vector<int> vec1 = { 2, 4, 6, 8, 10 };
    vector<int> vec2 = { 1, 3, 5, 7, 9 };

    vector<int> ret(vec1.size()); // 대상 범위
        
    transform( vec1.begin(), vec1.end(), vec2.begin(), ret.begin(), [](int v1, int v2){ 
        return v1 + v2;
    } );

    for_each( ret.begin(), ret.end(), [](int v){ // 결과 출력
        cout << v << " ";
    } );
}

▼출력

3 7 11 15 19

 

위의 예문을, 함수 객체( Function Object, Functor )를 사용해서 구현할 수도 있습니다.

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>   // plus 함수 객체 사용
using namespace std;

int main(){

    vector<int> vec1 = { 2, 4, 6, 8, 10 };
    vector<int> vec2 = { 1, 3, 5, 7, 9 };

    vector<int> ret(vec1.size()); // 대상 범위
        
    // std 함수 객체 사용
    transform( vec1.begin(), vec1.end(), vec2.begin(), ret.begin(), plus<int>() );

    for_each( ret.begin(), ret.end(), [](int v){
        cout << v << " ";
    });
}

위 예제에서 plus<T>는 C++ 표준 라이브러리에서 지원하는, 더하기 연산 함수 객체( functor )입니다.

이 객체를 사용하려면 먼저 다음의 파일을 포함해야 합니다.

#include <functional>

이 헤더 파일은 사칙연산뿐만 아니라 수많은 함수 객체( less, greater 등 )를 작성하여 제공하고 있습니다.

 

 

이 글과 관련 있는 글들

객체의 모든 원소를 순환하는 범위 기반 for 구문

함수 객체( function object, functor ) : operator()를 구현한 타입

간단한 함수 객체를 정의하기 위한 람다 표현식( lamda expression )

 

 

 

 

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유