对于没有\regex_replace_all:nnN

对于没有\regex_replace_all:nnN

我有一些想要读取和绘制的表格,每个表格都有自己的风格。为了方便起见,我喜欢使用相同的标签。以下是 MWE:

\documentclass{minimal}

\usepackage{pgfplotstable}

\begin{filecontents}{tabA.dat}
x   y
0   0
1   1
2   2
3   3
\end{filecontents}
\begin{filecontents}{tabB.dat}
x   y
0   1
1   2
2   3
3   4
\end{filecontents}

\pgfplotsset{compat=newest,
tabA/.style={color=red,mark=*},
tabB/.style={color=black,mark=o},
}

\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[legend,legend pos=south east]
            \addplot[tabA] table[x=x,y=y] {\tabA};\label{pgf:tabA}\addlegendentry{tabA}
            \addplot[tabB] table[x=x,y=y] {\tabB};\label{pgf:tabB}\addlegendentry{tabB}
        \end{axis}
    \end{tikzpicture}

\end{document}

\pgfplotsforeachinvoke我可以使用或实现相同的结果吗\foreach?例如

\begin{tikzpicture}
    \begin{axis}[legend,legend pos=south east]
        \pgfplotsinvokeforeach{tabA,tabB}{%
            % The following doesn't work, of course
            \addplot[#1] table[x=x,y=y] {\#1}; % <- Magic goes here 
        }
    \end{axis}
\end{tikzpicture}

当然,在这个简单的例子中,我可以简单地使用

\addplot[#1] table[x=x,y=y] {#1.dat};

但有时文件的名称不符合某种模式,或者有时我只想读取和存储一个表以便修改它或多次重复使用它。

答案1

欢迎来到 TeX.SE!有一件事总是有可能的:

  1. 编写一个宏,按照您想要的方式组装一个标记列表(这里,将一系列\addplot命令与适当的选项连接起来);

  2. 然后使用第二个宏(在我的代码中,由的第二个参数构造\foreachTable),输出类似的内容\begin{axis}[...]#1\end{axis},并#1用包含所有命令的先前组装的标记列表替换\addplot

这种技术总是有效(一旦第二个宏被展开,TeX 输入流就和你手动输入所有代码的状态完全相同)。因此,你可以使用它以编程方式生成表格、图片,以及任何你想要的东西。

完整代码:

\begin{filecontents}{tabA.dat}
x   y
0   0
1   1
2   2
3   3
\end{filecontents}

\begin{filecontents}{tabB.dat}
x   y
0   1
1   2
2   3
3   4
\end{filecontents}

\documentclass[tikz, border=2mm]{standalone}
\usepackage{xparse}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\ExplSyntaxOn
\seq_new:N \l__millo_plot_cmds_tl

\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3
  {
    \tl_clear:N \l__millo_plot_cmds_tl
    \clist_map_inline:nn {#1}
      {
        \tl_set:Nn \l_tmpa_tl {#3}
        \regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
        \tl_put_right:NV \l__millo_plot_cmds_tl \l_tmpa_tl
      }

    \exp_args:No #2 \l__millo_plot_cmds_tl
  }

\NewDocumentCommand \foreachTable { m m m }
  {
    \cs_set_protected:Npn \__millo_axis_func:n ##1 {#2}
    \millo_foreach_table_do_axis:nNn {#1} \__millo_axis_func:n {#3}
  }
\ExplSyntaxOff

\pgfplotsset{
  tabA/.style={color=red,mark=*},
  tabB/.style={color=black,mark=o},
}

\pgfplotstableread{tabA.dat}\tabA
\pgfplotstableread{tabB.dat}\tabB

\begin{document}

\begin{tikzpicture}
  \foreachTable{tabA, tabB}
    {
      \begin{axis}[legend, legend pos=south east]
        #1
      \end{axis}
    }
    { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }
\end{tikzpicture}

\end{document}

截屏

调用说明:

\foreachTable{tabA, tabB}
  {
    \begin{axis}[legend, legend pos=south east]
      #1
    \end{axis}
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

第一个参数是条目列表(每个条目指向一个\addplot命令)。

#1第二个参数是内部内容被自动生成的命令替换后将插入的内容\addplot

第三个参数指定每个自动生成的图的代码,并进行一些方便的替换:

  • #1替换为条目名称(此处:tabAthen tabB);

  • \myTable用由条目名称构建的控制序列标记替换(此处:\tabA对于第一个条目,\tabB对于第二个条目)。

如果您想手动添加更多图(此处,一个在自动生成的图之前,一个在自动生成的图之后),您可以例如执行以下操作:

\foreachTable{tabA, tabB}
  {
    \begin{axis}[legend, legend pos=south east]
      \addplot {sin(deg(\x))}; \addlegendentry{$\sin$}
      #1
      \addplot {sqrt(\x)};     \addlegendentry{$x\mapsto \sqrt{x}$}
    \end{axis}
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

在此处输入图片描述

对于没有\regex_replace_all:nnN

如果您的l3kernel年龄太大,无法拥有\regex_replace_all:nnN,您可以:

  • \cs_generate_variant:Nn \tl_replace_all:Nnn { Nno }在 之前添加\cs_new_protected:Npn \millo_foreach_table_do_axis:nNn #1#2#3

  • 更换线路

    \regex_replace_all:nnN { \c{myTable} } { \c{##1} } \l_tmpa_tl
    

    \exp_args:NNno
    \tl_replace_all:Nno \l_tmpa_tl { \myTable } { \use:c {##1} }
    

那么它应该可以工作在条件下不在\myTable括号内使用。例如,使用

\foreachTable{tabA, tabB}
  {
    ...
  }
  { \addplot[#1] table[x=x,y=y] \myTable; \addlegendentry{#1} }

代替:

\foreachTable{tabA, tabB}
  {
    ...
  }
  { \addplot[#1] table[x=x,y=y] {\myTable}; \addlegendentry{#1} }

相关内容