Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


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