對於沒有的人\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我可以使用or達到相同的結果嗎\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} }

相關內容