在 LaTeX 中在另一个循环内循环

在 LaTeX 中在另一个循环内循环

我正在尝试使用中的某些构造在另一个循环中创建一个循环etoolbox但我不知道如何创建它。

我想要获得如下输出C

伪代码

for (i in the list) {            
    for (j in the list) {  
        print(i,j)
    }
}

LaTeX 代码

例如,我不知道如何使用\dolistcsloopLaTeX 中的构造实现与上述相同的功能。

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

相关内容