
Quiero dividir una cadena en caracteres individuales, transformar cada carácter individualmente y luego volver a unirlos.
Algo como esto:
\newcommand{\drawaboxaroundit}[1]{...}
\newcommand{\glue}{+}
\explodethenjoin{abcdef}{\drawaboxaroundit}{\glue}
Pasando por alto cómo \drawaboxaroundit
podría funcionar (es sólo a modo ilustrativo, no es lo que realmente estoy haciendo), el resultado de este ejemplo sería algo como esto:
La intención es que \explodethenjoin{abc}{\drawaboxaroundit}{\glue}
se expanda a
\drawaboxaroundit{a}\glue\drawaboxaroundit{b}\glue\drawaboxaroundit{c}
Casi tengo una solución a mi problema conesta respuesta(aunque básicamente no sé nada sobre expl, así que no entiendo cómo funciona): esto procesa cada personaje individualmente pero no pega entre ellos.
Un enfoque (que no me parece un buen diseño) sería tomar \drawaboxaroundit
conciencia de su posición, es decir, el abc
ejemplo anterior se expandiría a
\drawaboxarounditwrapper{0}{\glue}{a}\drawaboxarounditwrapper{1}{\glue}{b}\drawaboxarounditwrapper{2}{\glue}{c}
con \drawaboxarounditwrapper
definido para ser algo como esto
\newcommand{\drawaboxarounditwrapper}[2]{
\ifthenelse{\equal{#1}{0}}{}{\glue}
\drawaboxaroundit{#2}
}
Otra opción sería dividir la cadena en carácter principal y cadena final. Algo como esto
\witheachcharacterinheadandtail{abcdef}{\drawaboxaroundit}{\glue\drawaboxaroundit}
donde \witheachcharacterinheadandtail{abcdef}{\foo}{\bar}
se expande hacia
\foo{a}\bar{b}\bar{c}\bar{d}\bar{e}\bar{f}
Este segundo enfoque parece ser mejor, pero no sé cómo implementar ninguno de estos enfoques ni si alguno de ellos es una buena idea en primer lugar.
¿Cómo puedo explotar, transformar y unir una cadena?Podemos asumir que las cadenas en cuestión son ASCII y no contienen comandos de látex, y todas las cadenas contendrán al menos dos caracteres (una cola siempre tendrá una longitud distinta de cero).
Respuesta1
\documentclass{article}
\def\xloop#1{\ifx\relax#1\else\xloopbody{#1}\expandafter\xloop\fi}
\newcommand\explodethenjoin[3]%
{\def\inter{\def\inter{#3}}%
\def\xloopbody##1{\inter#2{##1}}%
\xloop#1\relax
}
\begin{document}
\explodethenjoin{abcdef}{\fbox}{+}
\end{document}
La macro \xloop
itera sobre los tokens que la siguen hasta que encuentra \relax
. Se ha usadovarias veces en este sitio. Para cada token \xloopbody
se ejecuta la macro; al definirlo adecuadamente, los tokens se pueden procesar según sea necesario.
Respuesta2
Como TeX realmente no tiene cadenas, no necesita ningún comando específico para dividir una lista de tokens, ya es una lista de tokens distintos. De manera similar, no es necesario utilizar una macro de bucle explícita, ya que iterar sobre una lista de tokens es simplemente el comportamiento normal de tex.
\documentclass{article}
\def\zz#1{\def\zzsep{}\zzz#1\relax}
\def\zzz#1{\ifx\relax#1\else\zzsep\def\zzsep{+}\fbox{#1}\expandafter\zzz\fi}
\begin{document}
\zz{abcdef}
\end{document}
Respuesta3
Es muy fácil con xparse
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\splitstring}{mmO{}}
{
\spraff_string_split:nnn { #1 } { #2 } { #3 }
}
\seq_new:N \l_spraff_string_in_seq
\seq_new:N \l_spraff_string_out_seq
\cs_new_protected:Nn \spraff_string_split:nnn
{
% split the string at 'nothing'
\seq_set_split:Nnn \l_spraff_string_in_seq { } { #1 }
% change each item into '#2{<item>}'
\seq_set_map:NNn \l_spraff_string_out_seq \l_spraff_string_in_seq { #2 { ##1 } }
% use the sequence with '#3' in between items
\seq_use:Nn \l_spraff_string_out_seq { #3 }
}
\ExplSyntaxOff
\NewDocumentCommand{\boxit}{m}{\fbox{\strut#1}}
\begin{document}
\splitstring{abcdef}{\boxit}
\splitstring{abcdef}{\boxit}[${}+{}$]
\end{document}
Tenga en cuenta que la macro utilizada como segundo argumento \splitstring
debe definirse con \NewDocumentCommand
.