lunes, 30 de septiembre de 2024

Funciones. textos

Buscar y reemplazar (b)

Además de la función Replace() vista en la [entrada anterior], para la misma función también contamos con una segunda función, desarrollada ésta por los colaboradores de [wiki.open-office.es]: la función ReplaceAll() (reemplazar todo), a la que dedicaré esta entrada por el interés que tiene en si misma y para comparar con la solución anterior. 


Por eso de no perder el tiempo, paso a mostrar la sintaxis de la función:

Function ReplaceAll(cCadena As String, cBusca As String, optional cReemplaza As String) As String

  If IsMissing( cReemplaza ) Then cReemplaza = ""
  ReplaceAll = Join( Split( cCadena, cBusca ), cReemplaza )

End Function

Lo primero que te llamará la atención es lo breve su extensión frente a la de Replace(), algo que ilustras la diversidad de opciones que tenemos a nuestro alcance para dar solución, la misma solución, al mismo problema.

Lo segundo a destacar es la al menos aparente sencillez estructural de esta función frente a la anterior: en ReplaceAll() se simplifica el código eliminando el bucle y manteniendo únicamente un condicional. Cierto que la sensación de simplificación se ve acentuada por la formulación simplificada del condicional (If IsMissing( cReemplaza ) Then cReemplaza = "") frente a la formulación canónica en OOo Basic (1); también el modo en que se expresa el Return (ReplaceAll = Join( Split( cCadena, cBusca ), cReemplaza )), que ahorra la declaración de variables privadas en la función.

La función ReplaceAll() recibe tres parámetros, dos de ello obligados y el tercero opcional, y todo ellos de tipo String.  Los dos obligatorios hacen referencia a la cadena sobre la que se trabaja (cCadena) y la subcadena (palabra) que se pretende sustituir (cBusca); la opcional traslada a la función la subcadena (palabra) sustitutoria (cReemplaza). Precisamente para gestionar la ausencia de este parámetro se define el condicional If que incluye la función IsMissing() que devuelve el valor cadena vacía como alternativa para dicho parámetro (cReemplaza = "") (2)

El núcleo de la función está, no obstante, en la compleja expresión que se asocia al Return, ya que se realiza directamente, incluye la llamada a dos funciones Built-In vistas [aquí] y se presentan anidadas: Join(Split(cCadena, cBusca ), cReemplaza).

En esta expresión, la función Join() recibe como primer parámetro el valor que devuelve la función Split() (esto es, la matriz de las palabras que contiene la cadena-base, que constituye su primer parámetro y ha sido pasada como primer parámetro la función-madre) y como segundo (String de separación), el valor de la palabra sustitutoria.

Analizando el proceso de dentro a fuera, Split() devuelve una matriz compuesta por dos elementos: la subcadena que precede a la palabra que constituye su segundo parámetro (esto es, la palabra buscada) (La) y la subcadena que la sigue (de la pradera), omitiendo (puesto que sirve de separador) la palabra a sustituir (casa). 

Por su parte, la función Join() une los elementos de esa lista o matriz que le entrega la función Split() (que, como dijimos, constituye su primer parámetro, o sea, la matriz de subcadenas a unir), utilizando como elemento de unión precisamente la palabra que queremos reemplace a la que deseamos sustituir. De este modo, la palabra-enlace de la función Join() se sitúa entre las dos subcadenas que obtuvimos mediante la función Split(), resultando de ello un proceso de sustitución de una palabra-enlace (segundo parámetro de Split()) por otra palabra de enlace (segundo parámetro de Join()) (3). Todo esto se resume en que la función ReplaceAll() devuelve una cadena en la que una palabra es sustituida por otra, que es lo que se pretende con ella.

NOTA

(1) Sobre esta cuestión ver [esta entrada]
(2) En caso de que no pasemos una subcadena mediante el parámetro cReemplaza, su lugar será ocupado por una subcadena vacía. Personalmente no me gusta el efecto que deriva de ello, aunque evidentemente es una de las soluciones posibles.
(3) Entiendo que esta explicación comporta cierta dificultad, pero resulta necesaria para comprender el modo en que se emplean ambas funciones y el efecto que produce su uso. Obsérvese que, según vimos [en su momento], el segundo parámetro de ambas funciones tenía un significado funcional diferente al que se usa en la función RemoveAll(): aunque son fundamentales, no dejan de ser accesorios, pero en RemoveAll() resultan fundamentales (su uso combinado es el que facilita la sustitución de una palabra por otra). Esto da idea de las posibilidades que presentan ambas funciones, más allá de lo aparente.