# Extracting characters of two strings in a for loop

I have two strings of equal lengths, let's say abc and def (in reality they can be much longer). Both strings consist only of letters a-z, A-Z (no numbers, no special characters etc.). I need to extract out the characters individually from both strings, and use them pairwise in another macro that I have defined.

For e.g. For the two strings abc and def and some other macro \printchar[2]{#1,#2} that I have defined, I want to be able to pass the characters pair by pair into \printchar, that is,

\printchar{a}{d}
\printchar{b}{e}
\printchar{c}{f}


in perhaps, a for loop of some kind. So I guess the question is two-fold:

1. How to extract out characters from two input strings of equal lengths, character by character, and
2. Subsequently use them, pairwise, inside a macro. (and it should loop through all characters in the string).

## Pseudo-Code:

\documentclass[]{article}
\newcommand\printchar[2]{#1,#2}
\newcommand\foo[2]{% Takes in two strings
% <begin loop>
% Extracts out one character from both strings
\printchar{#1}{#2}%
% Continue loop until strings run out of characters
% <end loop>
}

\begin{document}
\foo{abc}{def} % Should print a,d,b,e,f
\end{document}


From some searching around, I think maybe the xstring package can do the first part? But I'm not too sure how to integrate it with a for loop to achieve what I want.

• Will both strings always consist of printable characters -- more precisely, characters with catcode "letter" and/or "other"? Or might the strings contain arbitrary characters, incl "special" characters such as % and {? – Mico May 2 '17 at 14:35
• Oh yes, good point. No, they will always be letters. (a-z, A-Z). I'll update it in the question – Troy May 2 '17 at 14:36
• Why the apparent haste to "accept" one of the answers? You can upvote good answers immediately, of course. Site guidelines suggest, though, waiting several hours and maybe even day before accepting the best answer. Hasty acceptance of an answer tends to completely discourage the posting of any further answers. – Mico May 2 '17 at 15:26
• Oops, sorry @Mico. I will keep that in mind in the future.. :x – Troy May 2 '17 at 15:31

Without any packages:

\documentclass[]{article}
\makeatletter
\newcommand\printchar[2]{#1,#2}
\def\parsefoo#1#2,#3#4|{%
\ifx\relax#1\relax%
\else%
\ifx\relax#3\relax%
\else%
\printchar{#1}{#3}%
\ifx\relax#2\relax%
\else%
\ifx\relax#4\relax%
\else%
,\edef\@footmp{#2,#4|}%
\expandafter\parsefoo\@footmp%
\fi%
\fi%
\fi%
\fi%
}
\newcommand\foo[2]{% Takes in two strings
% <begin loop>
% Extracts out one character from both strings
\edef\@footmp{#1,#2|}%
\expandafter\parsefoo\@footmp%
%\printchar{#1}{#2}%
% Continue loop until strings run out of characters
% <end loop>
}
\makeatother

\begin{document}
\foo{abc}{def} % Should print a,d,b,e,f
haha
\end{document}


The loop will stop when either strings runs out of items.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\foo}{mmm}
{% #1 is the macro to use, #2 is the first string, #3 is the second string
\troy_foo:Nnn #1 { #2 } { #3 }
}

\seq_new:N \l_troy_foo_first_seq
\seq_new:N \l_troy_foo_second_seq

\cs_new_protected:Nn \troy_foo:Nnn
{
% split the first string into items
\seq_set_split:Nnn \l_troy_foo_first_seq { } { #2 }
% split the second string into items
\seq_set_split:Nnn \l_troy_foo_second_seq { } { #3 }
% map over the two string
}
\ExplSyntaxOff

\newcommand{\printchars}[2]{#1#2\par}

\begin{document}

\foo{\printchars}{abc}{def}

\end{document}


A fully expandable variant:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewExpandableDocumentCommand{\loopstrings}{mmm}
{
\troy_loopstrings:Nnn #1 { #2 } { #3 }
}
\cs_new:Nn \troy_loopstrings:Nnn
{
\__troy_loopstrings:Nffff #1
{ \tl_head:n { #2 } } { \tl_head:n { #3 } }
{ \tl_tail:n { #2 } } { \tl_tail:n { #3 } }
}

\cs_new:Nn \__troy_loopstrings:Nnnnn
{
\bool_lazy_or:nnF { \tl_if_empty_p:n { #2 } } { \tl_if_empty_p:n { #3 } }
{
#1{#2}{#3}
\troy_loopstrings:Nnn #1 { #4 } { #5 }
}
}
\cs_generate_variant:Nn \__troy_loopstrings:Nnnnn { Nffff }
\ExplSyntaxOff

\newcommand{\printchars}[2]{#1#2\par}

\begin{document}

\loopstrings{\printchars}{abcd}{1234}

\loopstrings{\printchars}{abc}{1234}

\loopstrings{\printchars}{abcd}{123}

\end{document}

• Yay, faster than egreg :) – Skillmon May 2 '17 at 14:50
• @Skillmon Even with longer code! – egreg May 2 '17 at 14:51
• Just longer because of the many \ifx to end the loop if one argument runs out of tokens. – Skillmon May 2 '17 at 14:52
• @Skillmon +1 for both of your answers! Both seem to do fine for what I'm working on in reality, but I guess I'll accept @Skillmon's no packages answer, and a reward for being faster than egreg. :) – Troy May 2 '17 at 15:10

Here's a LuaLaTeX-based solution. (Exact same output as in @egreg's answer, hence no separate screenshot.)

%% to be compiled under LuaLaTeX
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function string_pair ( u , v )
for i=1,string.len(u) do
tex.sprint ( string.sub (u,i,i) .. string.sub (v,i,i) .. "\\par" )
end
end
\end{luacode}
\newcommand\foo[2]{\directlua{string_pair(\luastring{#1},\luastring{#2})}}

\begin{document}
\foo{abc}{def}
\end{document}


When I was having fun with strings (Looping over strings) I also made a macro for looping over two strings. However, after the replies I got there it seems that it is not a good solution since it does not use tail recursion. On the other hand, it has the advantage of being easy to understand and therefore I put it here.

\documentclass{article}

\begin{document}

\def\doubleloop<#1#2><#3#4>{%
\ifx\relax#1 \else
\ifx\relax#3 \else
[#1,#3]
\doubleloop<#2><#4>
\fi
\fi}

\def\loopstrings#1#2{\doubleloop<#1\relax><#2\relax>}

\verb|\loopstrings{abcd}{1234}| \loopstrings{abcd}{1234}

\verb|\loopstrings{abc}{1234}| \loopstrings{abc}{1234}

\verb|\loopstrings{abcd}{123}| \loopstrings{abcd}{123}

\end{document}


This can be turned into a macro using tail recursion:

\documentclass{article}

\begin{document}

\makeatletter
\def\doubleloop<#1#2><#3#4>{%
\ifx#1\relax
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\doubleloopaux{#1}{#2}{#3}{#4}}%
}
\def\doubleloopaux#1#2#3#4{%
\ifx#3\relax
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{[#1,#3]\doubleloop<#2><#4>}%
}
\makeatother

\def\loopstrings#1#2{\doubleloop<#1\relax><#2\relax>}

\verb|\loopstrings{abcd}{1234}| \loopstrings{abcd}{1234}

\verb|\loopstrings{abc}{1234}| \loopstrings{abc}{1234}

\verb|\loopstrings{abcd}{123}| \loopstrings{abcd}{123}

\end{document}

• @egreg: Thanks! I had been trying to convert it to tail recursion without success. I find this a really nice setup. If I understand it well, the \@firstofone just eliminates the braces? – Raoul Kessels May 8 '17 at 6:54
• Yes, but they're also necessary in order for \@gobble to work, in case the firs string has run off of items – egreg May 8 '17 at 7:02