I want to split a string into individual characters, transform each character individually, then join them back together.

Something like this:

\newcommand{\drawaboxaroundit}[1]{...}
\newcommand{\glue}{+}
\explodethenjoin{abcdef}{\drawaboxaroundit}{\glue}

Glossing over how \drawaboxaroundit might work (it's just for illustration, it's not what I'm really doing), the result for this example would be something like this:

enter image description here

The intention is for \explodethenjoin{abc}{\drawaboxaroundit}{\glue} will expand to

\drawaboxaroundit{a}\glue\drawaboxaroundit{b}\glue\drawaboxaroundit{c}

I nearly have a solution to my problem with this answer (although I know basically nothing about expl so I don't understand how it works) -- this processes each character individually but does not put glue between them.

One approach (which doesn't seem like good design to me) would be to make \drawaboxaroundit aware of its position, i.e. the above abc example would expand to

\drawaboxarounditwrapper{0}{\glue}{a}\drawaboxarounditwrapper{1}{\glue}{b}\drawaboxarounditwrapper{2}{\glue}{c}

with \drawaboxarounditwrapper defined to be something like this

\newcommand{\drawaboxarounditwrapper}[2]{
    \ifthenelse{\equal{#1}{0}}{}{\glue}
    \drawaboxaroundit{#2}
}

Another option would be to split the string into head character and tail string. Something like this

\witheachcharacterinheadandtail{abcdef}{\drawaboxaroundit}{\glue\drawaboxaroundit}

Where \witheachcharacterinheadandtail{abcdef}{\foo}{\bar} expands into

\foo{a}\bar{b}\bar{c}\bar{d}\bar{e}\bar{f}

This second approach seems to be better, but I don't know how to realize either of these approaches, or whether either is a good idea in the first place.

How can I explode-transform-join a string? We can assume the strings in question are ASCII and contain no latex commands, and all strings will contain at least two characters (a tail will always have nonzero length).

up vote 6 down vote accepted

enter image description here

\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}

The macro \xloop iterates over the tokens following it until it encounters \relax. It has been used several times on this site. For each token the macro \xloopbody is executed; by defining it appropriately, the tokens can be processed as needed.

It's a breeze with 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}

Beware that the macro used as second argument to \splitstring should be defined with \NewDocumentCommand.

enter image description here

As TeX doesn't really have strings, you do not need any specific commands to split up a token list, it is already a list of distinct tokens. Similarly you don't have to use an explicit loop macro as iterating over a token list is just the normal tex behaviour.

\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}

enter image description here

  • Isn't this exactly my solution (except for the wrapper and renaming)? And I'd call \zzz a loop since it calls itself ... Of course, my solution should maybe be better called your solution as the code is attributed to you in one post, or maybe to someone else since similar code appears in various style files and classes. – gernot Apr 13 '17 at 11:21
  • @gernot yes more or less, I probably just concentrated on making sure egreg didn't get a tick:-) (didn't notice this comment at the time for some reason) – David Carlisle May 27 '17 at 10:00
  • While two dogs are fighting for a bone, a third runs away with it ;-) – gernot May 28 '17 at 9:13

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.