我正在尝试使用中的某些构造在另一个循环中创建一个循环etoolbox
但我不知道如何创建它。
我想要获得如下输出C。
伪代码
for (i in the list) {
for (j in the list) {
print(i,j)
}
}
LaTeX 代码
例如,我不知道如何使用\dolistcsloop
LaTeX 中的构造实现与上述相同的功能。
\documentclass{minimal}
\usepackage{etoolbox}
\begin{document}
\def\mylist{}
\forcsvlist{\listadd\mylist}{1,2,3}
% Not sure how to acheive the double looping as the source code above using the \dolistloop construct of etoolbox.
\end{document}
答案1
这展示了如何使用嵌套循环etoolbox
\forlistloop
有两个参数:第二个参数是列表名称,第一个参数是列表处理器,即循环内要执行的操作。最好的办法是使用\newcommand
可扩展的宏。
这个列表处理宏可以有“任意”数量的参数,但最后一个参数始终用于处理当前列表元素,这取决于\forlistloop
。
在嵌套\forlistloop
方法中,这需要两个列表处理器宏。外层宏使用内部宏\forlistloop
和内部\grabfrominnerlist
宏。
请注意,没有关于如何进行嵌套循环的一般规则——排版决定了嵌套/循环顺序(以及TeX
分组等其他特定功能)。
\documentclass{article}
\usepackage{etoolbox}
\newcounter{rowcounter}
\newcounter{columncounter}
\newcounter{innercounter}
\newcommand{\addwithcounting}[3]{%
\stepcounter{#1}
\listadd{#2}{#3}
}
\newcommand{\grabfromouterlist}[2]{%
\setcounter{innercounter}{0}% Reset the inner counter
\forlistloop{\grabfrominnerlist{#2}}{#1} \\ % use the 2nd argument which is fed from the outer loop actually and process the list given as 1st argument.
}
\newcommand{\grabfrominnerlist}[2]{%
\stepcounter{innercounter}%
\ifnumless{\value{innercounter}}{\value{columncounter}}{%
a_{#1#2} & % typeset the matrix element with index of row and column number
}{%
a_{#1#2}% Final column, do not add a & character
}%
}
\usepackage{mathtools}
\begin{document}
\def\mycolumnlist{}
\def\myrowlist{}
\forcsvlist{\addwithcounting{rowcounter}{\myrowlist}}{1,2,3,4,5,6,7,8,9}
\forcsvlist{\addwithcounting{columncounter}{\mycolumnlist}}{1,2,3,4,5,6,7,8}
$\begin{pmatrix}
\forlistloop{\grabfromouterlist{\mycolumnlist}}{\myrowlist}
\end{pmatrix}$
$\begin{Bmatrix}
\forlistloop{\grabfromouterlist{\mycolumnlist}}{\myrowlist}
\end{Bmatrix}$
\end{document}
请注意,您不能在这里使用超过 10 列(无需进行更多工作),但这不是问题,etoolbox
而是底层矩阵环境的问题。
编辑
OP 给我发了一封邮件,其中有一些问题,所以我将尝试在这里用一些“扩展”版本来回答。
该\forlistloop
命令有两个参数:第一个是列表处理参数,第二个是列表的命令序列。
\forlistloop
所做的只是扫描列表元素,将列表分解为列表元素。在扫描过程中,此元素作为最后的参数。因此,例如,如果仅需显示列表,处理器命名\showlist
就足够了。
\newcommand{\showlist}[1]{%
#1 % <---- this is handled over by \forlistloop
}
\forlistloop{\showlist}{\mylist} % Does the job
现在,列表处理器当然可以拥有的不仅仅是参数,但是列表中的数据总是从右侧进入到左侧,因此总是从\forlistloop
或获取列表元素的最后一个参数\forlistcsloop
。
命令调用\forlistloop{\grabfromouterlist{\mycolumnlist}}{\myrowlist}
将循环遍历\myrowlist
内容,即示例中的行号。
这个行号,比如说8
,被输入到\grabfromouterlist{\mycolumnlist}{8}
然后等。由于\grabfromouterlist
它本身使用\grabfrominnerlist
,这将循环\mycolumnlist
并有效地使用数字8
等。
\documentclass{article}
\usepackage{etoolbox}
\newcounter{rowcounter}
\newcounter{columncounter}
\newcounter{innercounter}
\newcommand{\addwithcounting}[3]{%
\stepcounter{#1}
\listadd{#2}{#3}
}
\newcommand{\grabfromouterlist}[3][a]{%
\setcounter{innercounter}{0}% Reset the inner counter
\forlistloop{\grabfrominnerlist[#1]{#3}}{#2} \\ % use the 2nd argument which is fed from the outer loop actually and process the list given as 1st argument.
}
\newcommand{\grabfrominnerlist}[3][a]{%
\stepcounter{innercounter}%
\ifnumless{\value{innercounter}}{\value{columncounter}}{%
#1_{#2#3} & % typeset the matrix element with index of row and column number
}{%
#1_{#2#3}% Final column, do not add a & character
}%
}
\usepackage{mathtools}
\begin{document}
\def\mycolumnlist{}
\def\myrowlist{}
\forcsvlist{\addwithcounting{rowcounter}{\myrowlist}}{1,2,3,4,5,6,7,8,9}
\forcsvlist{\addwithcounting{columncounter}{\mycolumnlist}}{1,2,3,4,5,6,7,8}
$\begin{pmatrix}
\forlistloop{\grabfromouterlist[b]{\mycolumnlist}}{\myrowlist}
\end{pmatrix}$
$\begin{Bmatrix}
\forlistloop{\grabfromouterlist{\mycolumnlist}}{\myrowlist}
\end{Bmatrix}$
$\begin{Bmatrix}
\forlistloop{\grabfromouterlist[\sum]{\mycolumnlist}}{\myrowlist}
\end{Bmatrix}$
\end{document}
请注意可选的第一个参数的使用,默认为a
。此信息必须作为第一个参数在最外侧左侧给出。
答案2
例如这样的事情:
\long\def\for#1in#2#3{\expandafter\def\csname b:\string#1\endcsname{#3}%
\forinA#1#2,,}
\def\forinA#1#2,{\ifx,#2,\else
\def#1{#2}\csname b:\string#1\endcsname \expandafter\forinA\expandafter#1\fi}
\for\i in{a, bc, d}
{%
\for\j in{A, B, C}
{%
i=\i, j=\j;\par
}
}
答案3
一些想法expl3
:
\documentclass{article}
\usepackage{amsmath}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\doublelist}{m+O{}mO{}m}
{% #1 = first list, #2 = code to execute at the end of the inner cycle
% #3 = second list, #4 = code to execute between elements in the inner cycle
% #5 = two argument macro to which items are passed
\clist_map_inline:nn { #1 }
{
\clist_map_inline:nn { #3 }
{
#5 { ##1 } { ####1 } #4
}
#2
}
}
\ExplSyntaxOff
\newcommand{\coeff}[2]{$a_{#1,#2}$}
\begin{document}
\doublelist{i,j,k,l}[\par]{u,v,w}[, ]{\coeff}
\end{document}
答案4
for
这是一个基于 LuaLaTeX 的解决方案。给出了两个使用 Lua 循环构造的二维数组示例。第一个示例i,j
用括号将数组对括起来;第二个示例将它们嵌入到 LaTeXarray
环境中——请注意使用&
和\\
来分隔行内和跨行单元格。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for "luacode" environment
%% Define two Lua functions that work with two-dim. arrays
\begin{luacode}
function paren_array(m,n)
for i = 1,m do
for j = 1,n do
tex.sprint("("..i..","..j..") ")
end
tex.print("") -- force a line break
end
end
function subscript_array(ind,m,n)
for i=1,m do
for j=1,n do
tex.sprint(ind.."_{"..i..j.."}")
if j<n then
tex.sprint ( "&" ) -- cell separator (ampersand)
else
tex.sprint( "\\\\" ) -- end of row (two backslashes)
end
end
end
end
\end{luacode}
\begin{document}
%% call the first function
\directlua{ paren_array(9,9) }
\bigskip
%% call the second function from within a LaTeX "array" environment
$
A = \left[ \begin{array}{*{5}{c}}
\directlua{ subscript_array( "a",5,5 ) }
\end{array} \right]
$
\end{document}