# A newcommand for more than one formula

I have some formula such as z_{(h_{1},h_{2},h_{3})} and z_{(h_{4},h_{5},h_{6})}. How can one introduce a \newcommand{}{} for all of such formulas?

• Please confirm that the only things that differ between the two formulas are the level-two subscripts -- 1/2/3 vs. 4/5/6. Please also confirm that there are always exactly 3 items in the subscript position to the right of z. – Mico Sep 4 '17 at 19:15
• @Mico: Very optimistic ;-) – user31729 Sep 4 '17 at 19:16
• @Mico The difference is only in indices and they have always 3 items in subscript. – Fahim B Sep 4 '17 at 19:37
• @FahimB: What about \zz{1} that produces z_{(h_{1},h_{2},h_{3})}? – Werner Sep 4 '17 at 19:54

They forgot xinttools.

\documentclass{article}

\usepackage{xinttools}

% Thank you very much. I will be very thankful if you write the commands for
% z_{j_{1}(h_{1},h_{2})} and z_{k(h_{3},h_{4},h_{5})}

\newcommand{\zz}[2]{z_{#1(\xintFor ##1 in {#2}\do {h_{##1}\xintifForLast{}{,}})}}
\begin{document}

$\zz{j_{1}}{1,2} = \zz{k}{3, 4, 5}$

\end{document}


  \newcommand\zz[3]{z_{(h_{#1},h_{#2},h_{#3})}


then you can use and \zz{1}{2}{3} and \zz{4}{5}{6} or even \zz123 and \zz456

• +1. I was going to call the macro \zzz, to be mildly mnemonic of the fact that it takes 3 arguments... – Mico Sep 4 '17 at 19:43
• @Mico and there was I being fearful of Ulrike chiding me for using too many z and you comment I have too few. I can't win. – David Carlisle Sep 4 '17 at 19:44

It's not difficult to extend it to any number of subscripts:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{m}
{
z
\sp{}\sb
{
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nn \l_fahim_z_subscripts_seq { h\sb{##1} }
}
(\seq_use:Nn \l_fahim_z_subscripts_seq { , })
}
}
\seq_new:N \l_fahim_z_subscripts_seq
\ExplSyntaxOff

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

\end{document}


This can be generalized to different base letters and different processing of the subscripts. The trailing optional argument sets how to treat each item in the comma separated list, see the examples.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{O{z}mO{h\sb{##1}}}
{
#1
\sp{}\sb
{
\cs_set_protected:Nn \__fahim_z_subscript:n { #3 }
\clist_map_inline:nn { #2 }
{
\seq_put_right:Nn \l_fahim_z_subscripts_seq { \__fahim_z_subscript:n { ##1 } }
}
(\seq_use:Nn \l_fahim_z_subscripts_seq { , })
}
}
\seq_new:N \l_fahim_z_subscripts_seq
\ExplSyntaxOff

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

$\zz[Z]{1,2,3}[k_{#1}]$

$\zz{1,2,3}[(#1)]$

\end{document}


For more complex settings, I suggest a key-value syntax. Here the keys are var (for the name of the variable), outer to set the overall setting (default is just adding the parentheses) and inner for the sequence of actual subscripts. See the given examples. At any moment you can issue \zzset to change (in the current scope) one or more of the values.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\zz}{O{}m}
{
\group_begin:
\keys_set:nn { fahim/zz } { #1 }
\fahim_zz:n { #2 }
\group_end:
}

\NewDocumentCommand{\zzset}{m}
{
\keys_set:nn { fahim/zz } { #1 }
}

\keys_define:nn { fahim/zz }
{
var .tl_set:N = \l__fahim_zz_var_tl,
outer .code:n = \cs_set_protected:Nn \__fahim_zz_outer:n { #1 },
inner .code:n = \cs_set_protected:Nn \__fahim_zz_inner:n { #1 },
}

\seq_new:N \l__fahim_zz_subscripts_seq

\cs_new_protected:Nn \fahim_zz:n
{
\tl_use:N \l__fahim_zz_var_tl
\sp{} % a dummy superscript to lower the subscript
\sb
{
\__fahim_zz_outer:n
{
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nn \l__fahim_zz_subscripts_seq { \__fahim_zz_inner:n { ##1 } }
}
\seq_use:Nn \l__fahim_zz_subscripts_seq { , }
}
}
}
\ExplSyntaxOff

% initialize
\zzset{
var=z,
outer=(#1),
inner=h_{#1},
}

\begin{document}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

$\zz[var=Z,inner=k_{#1}]{1,2,3}$

$\zz[outer=i(#1)]{1,2,3}$

$\zz[outer=i(#1),inner=k_{#1}]{1,2,3}$

\end{document}


• I've taken the liberty of adding a screenshot. :-) – Mico Sep 4 '17 at 20:04
• Is it possible to use this method for formulas such as z_{i(h_{1},h_{2},h_{3})} and z_{k(h_{4},h_{5})}? – Fahim B Sep 12 '17 at 18:12
• @FahimB The new version is online. – egreg Sep 12 '17 at 21:35

It's not difficult to extend it to any number of subscripts and without using ExplSyntaxOn:

\def\zz#1{\zzA#1,,}
\def\zzA#1,{z_\bgroup(h_{#1}\zzB}
\def\zzB#1,{\ifx\end#1\end)\egroup \else ,h_{#1}\expandafter\zzB\fi}

$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$

\bye


EDIT If you need to add an index letter'' (i, j like in your comment), then it is possible to do using this code:

\def\zz#1#{z_\bgroup#1\zzI}
\def\zzI#1{\zzA#1,,}
\def\zzA#1,{(h_{#1}\zzB}
\def\zzB#1,{\ifx\end#1\end)\egroup \else ,h_{#1}\expandafter\zzB\fi}

$\zz i{1,2,3}+\zz j{4,5,6}=\zz{1,2,3,4,5,6}$

\bye

• Is it possible to use this method for formulas such as z_{i(h_{1},h_{2})} and z_{j(h_{3},h_{4},h_{5})}? – Fahim B Sep 12 '17 at 19:19
• @FahimB Yes, see above. – wipet Sep 12 '17 at 20:36
• Thank you very much. I will be very thankful if you write the commands for z_{j_{1}(h_{1},h_{2})} and z_{k(h_{3},h_{4},h_{5})}. – Fahim B Sep 12 '17 at 20:54
• OK: \zz j_1{1,2} and \zz k{3,4,5}. – wipet Sep 13 '17 at 4:10

Very easy with the listofitems package:

\documentclass{article}
\usepackage{listofitems}
\newcommand\zz[1]{
z_{(
\setsepchar{,}
\foreachitem\i\in\zlist{\ifnum\icnt=1\relax\else,\fi h_{\i}}
)}
}
\begin{document}
$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$
\end{document}


By the way, listofitems works in plain TeX, as well:

\input listofitems.tex
\def\zz#1{
z_{(
\setsepchar{,}
\foreachitem\i\in\zlist{\ifnum\icnt=1\relax\else,\fi h_{\i}}
)}
}
$\zz{1,2,3}+\zz{4,5,6}=\zz{1,2,3,4,5,6}$
\end


You could also use e-TeX. (It seems rather simple to me.) Assuming that you have three subsequent indices every time you would say

\newcommand*\zz[1]{%
\@tempcnta\numexpr#1+1\relax
\@tempcntb\numexpr#1+2\relax
z_{(%
h_{#1}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
)}
}


and then call \zz{1} resp. \zz{4}.

To add in a few generalisations, i.e. arbitrary number of indices and specified indices is not a big deal:

\newcommand*\zzz[2][h]{%
\def\forplus{\def\forplus{+}}
z_{(%
\@for\i:=#2\do{\forplus#1_{\i}}%
)}
}


Note the optional parameter for the subscripts of first order:

\begin{gather*}
\zzz{1,2,3}\\
\zzz{4,5,6}\\
\zzz[p]{7,11,13,17}
\end{gather*}


If you want to you can get really sophisticated by declaring something that acts like

\indexloop[<delimiter>][<format>]{<indices>}


where <format>:='<superscript>_<opt. delimiter><subscript><opt. delimiter>'

defined by

\makeatletter
\def\defaultsup{z}
\def\defaultsub{h}
\def\defaultdll{(}
\def\defaultdlr{)}
\def\defaultsep{+}
\def\indexloop{%
\kernel@ifnextchar[
{\indexl@op}
{\indexl@op[\defaultsup_\defaultdll\defaultsub\defaultdlr]}
}
\def\indexl@op[#1]{%
\kernel@ifnextchar[
{\indexl@@p[{#1}]}
{\indexl@@p[\defaultsep][{#1}]}
}
\def\indexl@@p[#1][#2]#3{%
\def\forsep{\def\forsep{#1}}
\def\customsup{}
\def\customsub{}
\def\customdll{}
\def\customdlr{}
\process@format#2\@end
\customsup_{%
\customdll
\@for\i:=#3\do{\forsep\customsub_{\i}}%
\customdlr
}%
}
\def\process@format#1_#2\@end{%
\def\customsup{#1}
\process@sub#2\@@end
}
\def\process@sub#1{
\ifx#1\@@end\else
\ifcat#1x
\edef\customsub{\customsub#1}
\else
\ifx\customdll\@empty
\def\customdll{#1}
\else
\ifx\customdlr\@empty
\def\customdlr{#1}
\fi
\fi
\fi
\expandafter\process@sub
\fi
}
\makeatother


Here is a short test of the last solution.

\begin{gather*}
\indexloop{1,2,3}\\
\indexloop{4,5,6}\\
\indexloop[z_(p)]{7,11,13,17}\\
\indexloop[-][z_\langle x\rangle]{8,9,10,12,14,15,16}\\
\indexloop[,][{a_[i]}]{1,2}
\end{gather*}


## Complete Code

% arara: pdflatex
\documentclass{article}
\usepackage{amsmath}

\makeatletter
\newcommand*\zz[1]{%
\@tempcnta\numexpr#1+1\relax
\@tempcntb\numexpr#1+2\relax
z_{(%
h_{#1}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
)}
}
\newcommand*\zzz[2][h]{%
\def\forplus{\def\forplus{+}}
z_{(%
\@for\i:=#2\do{\forplus#1_{\i}}%
)}
}
\def\defaultsup{z}
\def\defaultsub{h}
\def\defaultdll{(}
\def\defaultdlr{)}
\def\defaultsep{+}
\def\indexloop{%
\kernel@ifnextchar[
{\indexl@op}
{\indexl@op[\defaultsup_\defaultdll\defaultsub\defaultdlr]}
}
\def\indexl@op[#1]{%
\kernel@ifnextchar[
{\indexl@@p[{#1}]}
{\indexl@@p[\defaultsep][{#1}]}
}
\def\indexl@@p[#1][#2]#3{%
\def\forsep{\def\forsep{#1}}
\def\customsup{}
\def\customsub{}
\def\customdll{}
\def\customdlr{}
\process@format#2\@end
\customsup_{%
\customdll
\@for\i:=#3\do{\forsep\customsub_{\i}}%
\customdlr
}%
}
\def\process@format#1_#2\@end{%
\def\customsup{#1}
\process@sub#2\@@end
}
\def\process@sub#1{
\ifx#1\@@end\else
\ifcat#1x
\edef\customsub{\customsub#1}
\else
\ifx\customdll\@empty
\def\customdll{#1}
\else
\ifx\customdlr\@empty
\def\customdlr{#1}
\fi
\fi
\fi
\expandafter\process@sub
\fi
}
\makeatother

\begin{document}
\begin{gather*}
\zz{1}\\
\zz{4}
\end{gather*}

\begin{gather*}
\zzz{1,2,3}\\
\zzz{4,5,6}\\
\zzz[p]{7,11,13,17}
\end{gather*}

\begin{gather*}
\indexloop{1,2,3}\\
\indexloop{4,5,6}\\
\indexloop[z_(p)]{7,11,13,17}\\
\indexloop[-][z_\langle x\rangle]{8,9,10,12,14,15,16}\\
\indexloop[,][{a_[i]}]{1,2}
\end{gather*}
\end{document}


## Edit

Even the first solution can be more sophisticated by implementing the step length:

\newcommand*\zz[2][1]{%
\@tempcnta\numexpr#2+1*#1\relax
\@tempcntb\numexpr#2+2*#1\relax
z_{(%
h_{#2}+h_{\the\@tempcnta}+h_{\the\@tempcntb}%
)}
}


$\zz[2]{0}$ would then compile to z_{h_0+h_2+h_4} as expected.