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
등 )를 작성하여 제공하고 있습니다.
이 글과 관련 있는 글들
함수 객체( function object, functor ) : operator()를 구현한 타입
간단한 함수 객체를 정의하기 위한 람다 표현식( lamda expression )