如何在不解析 Latex 的情况下创建紧凑的数据结构

如何在不解析 Latex 的情况下创建紧凑的数据结构

假设我有 100 个节点,我想绘制 100 次,每次都略有变化。我不想每次都复制/粘贴所有代码,那会造成大量重复和大量样板代码。因此,我正在考虑制作一个紧凑的数据结构来保存这些值。

问题是,用 Latex 的方式实现这个无需解析也就是说,如果不为自定义数据结构编写自定义解析器,如何实现这一点。

需要解析的示例数据结构如下:

\mynodes{1:red,2:blue,3:yellow,....}

这将为您提供一个以逗号分隔的列表id:color,然后您可以对其进行解析。

不过,我想知道是否有一种方法可以不进行解析就做到这一点。例如(假设存在 100 个属性1-100):

\mynodes{1=red,2=yellow}

但这个例子太简单了,每个 id 可能会有多个值。所以更像是:

\mynodes{1=\keys{color=red,size=1cm},2=\keys{color=yellow,size=1cm},...}

如果您有一个属性和值的查找表,则可以缩短此过程,例如:

\mynodes{1=\v{c=r,s=1},2=\v{c=y,s=1},...}

然后,这将为您提供一个etoolbox要迭代的对象列表。想知道这样的事情是否可行,并阐明如何实现这一点。

最终结果将是更紧凑的数据结构,无需使用任何解析。

答案1

我建议一种expl3方法。我们将节点数据存储在属性列表中;对于节点 1,属性1将包含整个数据集;我们还为特定数据添加属性1color和。1size

可以使用 检索数据\getmynode

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\mynodes}{m}
 {
  \prop_set_from_keyval:Nn \l_pollard_nodes_prop { #1 }
  \prop_map_inline:Nn \l_pollard_nodes_prop { \pollard_add_property:nn { ##1 } { ##2 } }
 }
\NewExpandableDocumentCommand{\getmynode}{mm}
 {% #1 = node number, #2 = property
  \prop_item:Nn \l_pollard_nodes_prop { #1#2 }
 }

\keys_define:nn { pollard/nodes }
 {
  color .code:n = \prop_put:Nxn \l_pollard_nodes_prop { \l__pollard_nodes_temp_tl color } { #1 },
  size  .code:n = \prop_put:Nxn \l_pollard_nodes_prop { \l__pollard_nodes_temp_tl size  } { #1 },
 }

\prop_new:N \l_pollard_nodes_prop
\cs_generate_variant:Nn \prop_put:Nnn { Nx }

\cs_new_protected:Nn \pollard_add_property:nn
 {
  \tl_set:Nn \l__pollard_nodes_temp_tl { #1 }
  \keys_set:nn { pollard/nodes } { #2 }
 }

\ExplSyntaxOff

\begin{document}

\mynodes{1={color=red,size=1cm},2={color=yellow,size=2cm},}

Node 1 -- color: \getmynode{1}{color}, size: \getmynode{1}{size}

Node 2 -- color: \getmynode{2}{color}, size: \getmynode{2}{size}

\end{document}

enter image description here

简写形式:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\mynodes}{m}
 {
  \prop_set_from_keyval:Nn \l_pollard_nodes_prop { #1 }
  \prop_map_inline:Nn \l_pollard_nodes_prop { \pollard_add_property:nn { ##1 } { ##2 } }
 }
\NewExpandableDocumentCommand{\getmynode}{mm}
 {% #1 = node number, #2 = property
  \prop_item:Nn \l_pollard_nodes_prop { #1#2 }
 }

\keys_define:nn { pollard/nodes }
 {
  color .code:n = \prop_put:Nxn \l_pollard_nodes_prop { \l__pollard_nodes_temp_tl color } { #1 },
  size  .code:n = \prop_put:Nxn \l_pollard_nodes_prop { \l__pollard_nodes_temp_tl size  } { #1 },
  c     .code:n = \prop_put:Nxx \l_pollard_nodes_prop
                   { \l__pollard_nodes_temp_tl color }
                   { \__pollard_nodes_color:n { #1 } },
  s     .code:n = \keys_set:nn { pollard/nodes } { size=#1cm }
 }

\prop_new:N \l_pollard_nodes_prop
\cs_generate_variant:Nn \prop_put:Nnn { Nxn, Nxx }

\cs_new_protected:Nn \pollard_add_property:nn
 {
  \tl_set:Nn \l__pollard_nodes_temp_tl { #1 }
  \keys_set:nn { pollard/nodes } { #2 }
 }

\cs_new:Nn \__pollard_nodes_color:n
 {
  \str_case:nn { #1 }
   {
    {r}{red}
    {y}{yellow}
    % define the others you need
   }
 }

\ExplSyntaxOff

\begin{document}

\mynodes{1={color=red,size=1cm},2={color=yellow,size=2cm},}

Node 1 -- color: \getmynode{1}{color}, size: \getmynode{1}{size}

Node 2 -- color: \getmynode{2}{color}, size: \getmynode{2}{size}

\mynodes{3={c=r,s=1}}

Node 3 -- color: \getmynode{3}{color}, size: \getmynode{3}{size}

\end{document}

enter image description here

答案2

如果您想尽可能避免解析,并且所有值都具有相同的属性列表,您可以让 TeX 使用宏调用列表作为参数来解析您的输入:

\documentclass{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\newcommand\mynodes[1]{%
  \begingroup
    \renewcommand\do[3]{%
      Node ##1 has color ``##2'' and size ``##3''.\\%
    }%
    #1%
  \endgroup
}
\begin{document}
\mynodes{\do{1}{red}{1cm}\do{2}{yellow}{1cm}}
\end{document}

enter image description here

答案3

我不完全确定您需要解析到什么级别\keys,但我确信该listofitems包可以为您解析它。

\documentclass{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{listofitems}
\newcommand\mynodes[1]{%
  \setsepchar{,/=}
  \readlist\mynodelist{#1}%
  \foreachitem\x\in\mynodelist{%
    node \mynodelist[\xcnt,1] is as follows:
     \detokenize\expandafter\expandafter\expandafter{\mynodelist[\xcnt,2]}%
    \par%
  }%
}
\begin{document}
\mynodes{1=\keys{color=red,size=1cm},2=\keys{color=yellow,size=1cm}}
\end{document}

enter image description here

例如,进一步解析键:

\documentclass{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{listofitems}
\newcommand\mynodes[1]{%
  \setsepchar{,/=}
  \readlist\mynodelist{#1}%
  \foreachitem\x\in\mynodelist{%
    node \mynodelist[\xcnt,1] is as follows:\\
     \expandafter\expandafter\expandafter\parsekeys\mynodelist[\xcnt,2]%
     \readlist\keylist{\tmp}%
     \foreachitem\y\in\keylist{The key ``\keylist[\ycnt,1]'' 
        has a value of ``\keylist[\ycnt,2]''.\\}%
    \par%
  }%
}
\def\parsekeys\keys#1{\gdef\tmp{#1}}
\begin{document}
\mynodes{1=\keys{color=red,size=1cm},2=\keys{color=yellow,size=1cm}}
\end{document}

enter image description here

\keys如果您避免在节点列表中支撑实际内容,那么listofitems可以更轻松地一举完成,而不是像\readlist我的第二个代码块中所示的那样嵌套。

因此,以下代码使用输入语法也会产生上述结果\mynodes{1:color=red,size=1cm;2:color=yellow,size=1cm}

\documentclass{article}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{listofitems}
\newcommand\mynodes[1]{%
  \setsepchar{;/:/,/=}
  \readlist\mynodelist{#1}%
  \foreachitem\x\in\mynodelist{%
    node \mynodelist[\xcnt,1] is as follows:\\
     \foreachitem\y\in\mynodelist[\xcnt]{The key 
        ``\mynodelist[\xcnt,2,\ycnt,1]'' 
        has a value of ``\mynodelist[\xcnt,2,\ycnt,2]''.\\%
     }%
    \par%
  }%
}
\begin{document}
\mynodes{1:color=red,size=1cm;2:color=yellow,size=1cm}
\end{document}

通过上述代码中的单个操作\readlist,所有输入都会立即存储在数组中\mynodelist

\mynodelist[<node-number>,2,<key number>, 1]给出关联的密钥,并

\mynodelist[<node-number>,2,<key number>, 2]给出相关的键值。

相关内容