我想获取 arrajob 数组的长度,遗憾的是该包不提供此功能。目前,每当我添加或删除数组中的元素时,我都必须手动调整长度变量,这很烦人。
我正在使用 LuaLaTeX;我写了下面的代码,它似乎应该可以完成工作
\documentclass{article}
\usepackage{arrayjob}
\usepackage{ifthen}
\usepackage{etoolbox}
\newarray\Test%
\readarray{Test}{%
A & B & C%
}
\newcommand{\Length}[1]{
\newboolean{done}
\setboolean{done}{false}
\directlua{i = 1}
\whiledo{\NOT\boolean{done}}{
\def\Iteration{\directlua{tex.print("\\#1(" .. i .. ")")}}
\ifx\Iteration\empty
\setboolean{done}{true}
\fi
%% \ifnum\directlua{tex.print(i)}=11
%% \setboolean{done}{true}
%% \fi
%% \directlua{tex.print(i .. " \\#1(" .. i .. ")")}
\directlua{i = i + 1}
}
\directlua{tex.print(i)}
}
\begin{document}
\Length{Test}
\end{document}
但实际上它只是挂起了。取消注释循环末尾的块将产生以下输出:
显示所有参数似乎都是正确的,但 \ifx 无法识别该字符串为空。我也尝试将其与另一个空数组元素的宏进行比较,并尝试了 \ifthanelse 和 etoolbox 的 \ifstrempty,但无济于事。
还有其他更好的方法来查找数组的长度吗?或者,您知道上述代码的问题是什么吗?
答案1
我建议改用expl3
。它不仅为这类内容提供序列,还允许在其\ExplSyntaxOn
/\ExplSyntaxOff
块内使用空格和换行符,而不会生成实际的空格和段落。如果没有它,您必须隐藏这些内容,以免在输出中添加错误的空格。
即使您想继续使用arrayjob
,您可能也想将其称为arrayjobx
。这是一个较新的版本,它使用命令名称\arrayx
而不是\array
因为使用会覆盖 LaTeX 的矩阵\array
内置环境。{array}
然后,有一种更简单、更可靠的方法来获取数组的长度:arrayjobx
为每个名为 的数组定义ArrayName
一个\total@ArrayName
包含长度的宏。当然,默认情况下您不能\total@ArrayName
直接输入,因为@
不能出现在控制序列中,所以您需要在\makeatletter
/之间使用它\makeatother
或通过 访问它\csname
。既然你想要一个基于名称的包装器,\csname
那么正确的工具就是:
\documentclass{article}
\usepackage{arrayjobx}
\usepackage{ifthen}
\usepackage{etoolbox}
\newarray\Test
\readarray{Test}{%
A&B&C&&D%
}
\newcommand \Length [1] {%
\begincsname total@#1\endcsname
}
\begin{document}
\Length{Test}
\end{document}
答案2
正如@DavidCarlisle 所说,这似乎是 \ifx 扩展的问题。
\ifx\Iteration\empty
\setboolean{done}{true}
\fi
我认为\ifx
比较字符串并会扩展其参数,直到找到一个文字值,但实际上它会比较代币并精确扩展。
而\empty
扩展为空标记\Iteration
会扩展一次为\directlua{tex.print("\\#1(" .. i .. ")")}
,这当然是不是一个空的标记。
我的解决方案是运行 arrayjob \checkArrayName
,将值放入\cacheddata
。然后我使用\cacheddata
它将其扩展一次为正确的值。
我还需要修复两个小错误,一个是仅在循环未完成时增加,并且从最后的一个两个中减去一个i
,因为循环超出了界限(并且 arrayjob 是 1 索引的)。
\documentclass{article}
\usepackage{arrayjob}
\usepackage{ifthen}
\newarray\Test
\readarray{Test}{
A & B & C
}
\newcommand{\Length}[1]{
\newboolean{done}
\setboolean{done}{false}
\directlua{i = 1}
\whiledo{\NOT\boolean{done}}{
\directlua{tex.print("\\check#1(" .. i ..")")}
%% \directlua{tex.print(i .. " \\cachedata")}
\ifx\cachedata\empty
\setboolean{done}{true}
\else
\directlua{i = i + 1}
\fi
}
\directlua{tex.print(i - 1)} % Last i is already out of bounds
}
\begin{document}
\Length{Test}
\end{document}
可能有更优雅的方法来解决代码中的原始问题,即使用一些 tex 原语来控制扩展,但上述代码确实正确地回答了原始问题。
取消注释注释行以查看更多详细信息: