我创建了一个 foreach 语句,使用expl3
和TikZ/pgf
:
\documentclass{article}
\usepackage{tikz}
\setlength{\parindent}{0cm}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \Counter #1 \Stopper { \tl_length:n {#1} }
\ExplSyntaxOff
\pgfmathdeclarefunction{countarray}{1}{\edef\pgfmathresult{\Counter#1\Stopper}}
\begin{document}
%array with names
\def\names{{"Katie","Frank","Laura"}}
%find the last element index
\pgfmathtruncatemacro{\Last}{countarray(\names) - 1}
%print all the elements of array
\foreach \i in {0,...,\Last} {%
\i: \pgfmathparse{\names[\i]}\pgfmathresult\\
}
\end{document}
打印此内容:
假设我想对不同的名称使用不同的颜色(或设置任何其他参数)。得到如下结果:
Katie\\
\textcolor{blue}{Frank}\\
Laura
在 Perl 中,我会做这样的事情:
my @data = (
{"text" => "Katie"},
{"text" => "Frank", "color" => "blue"},
{"text" => "Laura"});
foreach(@data)
{
if(defined($_->{color}))
{
print "\textcolor\{$_->{color}\}\{$_->{text}\}";
}
else
{
print $_->{text};
}
print "\\\\";
}
有可能实现这一点expl3
吗?
答案1
我不知道,expl3
但在 TikZ 中是可能的,或者更确切地说,在 中是可能的pgfkeys
。由于 LaTeX3 有一个l3keys
子模块,我认为基本相同的想法在那里有效。您可以像在 Perl 中一样创建数据结构:
\pgfkeys{
/names/.cd,
make name/.style = {
#1/color/.initial = black
},
make name/.list = {Katie, Frank, Laura},
Frank/color = blue
}
然后你可以通过以下方式提取名称的颜色:
\newcommand\getcolor[1]{%
\pgfkeysgetvalue{/names/#1/color}%
}
它完全可扩展,可用于任何需要名称颜色的地方。当然,对于此示例,不需要单个子项Frank/color
(您可以只设置Frank/.initial = blue
),但如果您想要更多属性,也可以通过为它们提供自己的命名子项来添加它们。
答案2
这最终并没有回答这个问题:
有可能实现这一点
expl3
吗?
因此它被标记为社区维基。
除了处理的有趣方面之外expl3
,这项工作完全可以通过 TikZ foreach 的标准语法与xstring
:
\documentclass{article}
\usepackage{tikz} % won't work just with pgffor
\setlength{\parindent}{0cm}
\usepackage{xstring}
\begin{document}
\foreach \name [count=\i from 0]in{Katie,Frank=>blue,Laura=>red}{
\IfSubStr{\name}{=>}{% true
\StrCut{\name}{=>}\xname\namecol
\i: \textcolor{\namecol}{\xname}\par%
}{% false
\i: \name\par%
}
}
\end{document}
这提供了:
背后的想法大致如下:
- 查找分隔符字符串(
=>
在示例中); - 如果存在,将字符串剪成两部分(名称和颜色)并使用它们;
- 如果不存在,则使用标准语法。
当然,也可以:
- 更改分隔符字符串;
- 做更复杂的事情(即添加更多属性:只需嵌套一些条件,或者以更简单的方式,每个属性定义一个分隔符字符串)。
答案3
假设我们希望代码支持文本的 2 个属性:颜色和斜体。首先我们定义 plist:
%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}
%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}
%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}
请注意,expl3 不支持名称中的数字,这就是我使用_a
, _b
,的原因_c
。
然后将所有 plist 放入一个序列中:
%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }
然后我们循环遍历序列并在必要时将适当的标记放到文本中:
\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
\prop_get:NnN #1 { text } \__text
\prop_get:NnNT #1 { color } \color_tl
{
\protected@edef \__text {\textcolor{\color_tl}{\__text}}
}
\prop_get:NnNT #1 { italic } \italic_tl
{
\protected@edef \__text {\textit{\__text}}
}
\__text\\
}
总共有以下代码:
\documentclass{article}
\usepackage{expl3}
\usepackage{color}
\setlength\parindent{0pt}
\begin{document}
\makeatletter
\ExplSyntaxOn
%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}
%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}
%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}
%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }
\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
\prop_get:NnN #1 { text } \__text
\prop_get:NnNT #1 { color } \color_tl
{
\protected@edef \__text {\textcolor{\color_tl}{\__text}}
}
\prop_get:NnNT #1 { italic } \italic_tl
{
\protected@edef \__text {\textit{\__text}}
}
\__text\\
}
\ExplSyntaxOff
\makeatother
\end{document}
这将打印: