# Generate comma separated list with some non-empty strings

I'm trying to generate a comma separated list that uses strings that may or may not be empty. For example \mylist{\stringA,\stringB,\stringC} would expand to A, C if B is empty or B, C if A is empty, etc.

In case it matters, the strings are generated with xstring, for example something like \StrBetween[3,4]{\longstring}{text:}{,}[\stringC] which may or may not be empty depending on whether the condition is met.

I'm pretty sure that I saw something similar somewhere, some time, but I just can't find it.

This might be done with pure expansion, but since you're using xstring it's not really necessary:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\mylist}{ m o }
{
\clist_clear:N \l_tmpa_clist
\clist_map_inline:nn { #1 }
{
\clist_put_right:No \l_tmpa_clist { ##1 }
}
\IfNoValueTF{#2}
{ \l_tmpa_clist }
{ \clist_set_eq:NN #2 \l_tmpa_clist }
}
\ExplSyntaxOff

\newcommand\stringA{A}
\newcommand\stringB{}
\newcommand\stringC{C}

\begin{document}

\mylist{\stringA,\stringB,\stringC}

\mylist{\stringA,\stringB,\stringC}[\listA]

\show\listA

\end{document}


The \show\listA command produces

> \listA=macro:
->A,C.


Without an optional argument the result will be simply printed.

If you want to print the resulting list with a space following the comma, then a different approach is needed:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\mylist}{ m }
{
\seq_clear:N \l_tmpa_seq
\clist_map_inline:nn { #1 }
{
\tl_if_empty:oF { ##1 } { \seq_put_right:No \l_tmpa_seq { ##1 } }
}
\seq_use:Nn \l_tmpa_seq {,~}
}
\ExplSyntaxOff

\newcommand\stringA{A}
\newcommand\stringB{}
\newcommand\stringC{C}

\begin{document}

\mylist{\stringA,\stringB,\stringC}

\end{document}


In case you want to avoid that \newcommand{\stringB}{ } prints a space, use \tl_if_blank:oF instead of \tl_if_empty:oF.

• Thanks. Can you help me altering the code so as to not ignore white spaces in the list? I would like A, C. – Jörg Apr 14 '14 at 16:21
• @Jörg That's a different thing, then. So you want just to print the items? – egreg Apr 14 '14 at 16:22
• Well, yes. Printing the items and the respective commas. Your solution is great - I like the \show\listA, but just with an extra whitespace between items. – Jörg Apr 14 '14 at 16:24

Try the following:

\documentclass{article}
\usepackage{etoolbox}
\makeatletter
\def\ifemptyarg#1{% https://tex.stackexchange.com/a/58638/5764
\if\relax\detokenize{#1}\relax % H. Oberdiek
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
\makeatother
\providecommand{\listcomma}{}
\newcommand{\mylist}[2][,]{%
\renewcommand*{\do}[1]{% How to process each item
\expandafter\ifemptyarg\expandafter{##1}
{}% Do nothing
{\unskip\listcomma{} \penalty0 ##1}% Print <,> <space> <item>
}%
\docsvlist{#2}% Process list
}
\begin{document}
\def\strA{strA}
\def\strB{strB}
\def\strC{}
\def\strD{strD}
\mylist{\strA,\strB,\strC,\strD}
\end{document}


The process above uses one of the options specified in How to iterate over a comma separated list?.