5.1.3c3 Función transform()
§1 Prototipo
Este algoritmo, descrito en el fichero de cabecera <algorithm>, se presenta sobrecargado en dos versiones con cuatro y cinco argumentos respectivamente:
template <class InputIterator, class OutputIterator,
class UnaryOperation>
OutputIterator
transform (InputIterator first,
InputIterator last,
OutputIterator result,
UnaryOperation op);
template <class InputIterator1, class InputIterator2,
class OutputIterator, class BinaryOperation>
OutputIterator
transform (InputIterator1 first1,
InputIterator1 last1,
InputIterator2 first2,
OutputIterator result,
BinaryOperation binary_op);
§2 Descripción
§2.1 La primera versión utiliza dos iteradores de entrada que
delimitan un rango [first, last) en el contenedor de entrada; un iterador de salida result,
que define el comienzo del rango de salida, y una función unaria op
(recibe un argumento) que define la transformación a realizar sobre los
elementos de la serie de entrada antes de escribirlos en la salida. En caso que los contenedores de
entrada y salida sean el mismo, el algoritmo realiza la operación
"in-place" ( 5.1.3).
El algoritmo devuelve un iterador de salida res definido por: res = result + (last - first).
La definición formal sería decir que este algoritmo asigna a cada elemento del contenedor de salida de iterador i en el rango [result, result + (last - first)) un nuevo valor igual a op(*(first + (i - result)).
Se exige que la invocación op(*(first + N)) no altere el contenido del elemento *(first + N). Es decir, que no tenga efectos laterales sobre el argumento utilizado.
Ejemplo:
Utilizando sendas matrices como contenedores de entrada y salida, utilizamos el algoritmo transform para hacer que los miembros da la matriz de salida sean el cubo de los de entrada.
#include <iostream>
#include <algorithm>
using namespace std;
int p3 (int n) { return n*n*n; }
void main() { // ===============
int mDigi [] = {0,1,2,3,4,5,6,7,8,9};
int mDigo [10];
transform(mDigi, mDigi+10, mDigo, p3);
for (int i=0; i<10; i++)
cout << "mDigo[" << i << "] => " <<mDigo[i] << endl;
}
Salida:
mDigo[0] => 0
mDigo[1] => 1
mDigo[2] => 8
mDigo[3] => 27
mDigo[4] => 64
mDigo[5] => 125
mDigo[6] => 216
mDigo[7] => 343
mDigo[8] => 512
mDigo[9] => 729
Comentario:
En este caso, el algoritmo utiliza la función unaria p3, que recibe un entero y devuelve el cubo del valor recibido. Esta función es invocada 10 veces (mDigi+10 - mDigi) utilizando sucesivamente cada elemento del contenedor de entrada mDigi como argumento. El valor devuelto es asignado a cada elemento del contenedor de salida (mDigo) a partir de la posición señalada por el tercer argumento.
§2.2 La segunda forma realiza la operación binaria binary_op entre dos
secuencias, colocando el resultado de la computación en una tercera. Para esto utiliza cuatro argumentos (además del
mencionado): los dos primeros se utilizan para definir el rango de
entrada de la primera secuencia [first1, last1); el tercero first2,
define el comienzo de la segunda secuencia; finalmente, el cuarto argumento, result,
define el punto de inicio de la secuencia de salida. Como puede
comprobarse, este algoritmo es capaz de utilizar dos contenedores distintos como entrada y situar el resultado en un tercero,
aunque la secuencia de salida también podría ser cualquiera de las de entrada. Por ejemplo, transform podría coger los
elementos de dos secuencias numéricas, sumarlos dos a dos, y colocar el resultado en un tercer contenedor.
El algoritmo devuelve un iterador de salida res definido por: res = result + (last1 - first1).
El algoritmo asigna a cada elemento del contenedor de salida de iterador i en el rango [result, result + (last1 - first1)) un nuevo valor igual a:
binary_op(*(first1 + (i - result), *(first2 + (i - result)));
Se exige que binary_op no tenga efectos laterales sobre sus argumentos. Es decir, que la invocación de binary_op(*(first1 + N), *(first2 + N)) no altere ninguno de los elementos *(first1 + N) o *(first2 + N).
Ejemplo:
Definimos una función binaria stringRepeat que será utilizada como argumento de transform:
string stringRepeat (const string& base, int number) {
string result;
// inicialmente result esta vacío
while (number--) result += base; // construir el resultado
return result;
// devolver el resultado
}
Esta función devuelve un string que se construye replicando el string base recibido como argumento, el número de veces indicado en el argumento number.
La siguiente invocación a transform() produce el efecto deseado:
list<string> words;
list<int> counts;
...
transform (words.begin(), words.end(),
counts.begin(), words.begin(), stringRepeat);
Transformando las palabras uno, dos, tres con los valores 3, 2, 3 produce el resultado siguiente:
unounouno,dosdos,trestrestres
§3 Complejidad
Según la versión utilizada, se realizan last1 - first1 ejecuciones del código op o binary_op.