如何用動態內容填入動態產生的表格?

如何用動態內容填入動態產生的表格?

如何動態生成表格並用動態資料填充表格?

例:假設我有

\def\N{10}

我想產生一個包含\N列的表格,其中每列的頂部單元格包含列的編號,例如

\begin{tabular}{|c|c|c|...|c|}
1 & 2 & 3 & ... & N
\end{tabular}

這是我得到的最接近的:

\newtoks\cols
\cols={}
\newcounter{i}
\setcounter{i}{1}
\loop
\cols=\expandafter{\the\cols \arabic{i}}
\ifnum\value{i}<\N
\cols=\expandafter{\the\cols &}
\stepcounter{i}
\repeat

\begin{tabular}{|*{\N}{c|}}
\the\cols
\end{tabular}

但由於\expandafter,這給了我十列,每列包含一個 10。

有沒有辦法執行部分擴充之類的操作?我只想擴展 ,\arabic{i}但當然不是&.

答案1

問題是這一行:

\cols=\expandafter{\the\cols \arabic{i}}

\cols是一個令牌暫存器,因此\arabic{i}不會被擴充。使用附加\expandafter並列印計數器值而不是\arabic幫助:

\cols=\expandafter{\the\expandafter\cols\the\value{i}}

完整範例:

\documentclass{article}

\newtoks\cols
\newcounter{i}
\newcount\N

\begin{document}
  \N=10
  \cols={}
  \setcounter{i}{1}
  \loop
    \cols=\expandafter{\the\expandafter\cols\the\value{i}}
  \ifnum\value{i}<\N
    \cols=\expandafter{\the\cols &}
    \stepcounter{i}
  \repeat
  \begin{tabular}{|*{\N}{c|}}
    \the\cols
  \end{tabular}
\end{document}

結果

可擴充版本

以下範例使用 e-TeX 的\numexpr.要注意保持穩定的\if築巢,並且&不能太早發現。

\documentclass{article}

\newcount\N

\makeatletter
\newcommand*{\Ncols}{%
  \Ncols@aux{1}%
}
\newcommand*{\Ncols@aux}[1]{%
  \ifnum#1>\N
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {% 
    \ifnum#1<2 \expandafter\@gobble\fi\Ncols@amp
    #1%
    \expandafter\Ncols@aux\expandafter{\the\numexpr(#1+1)}%
  }%
}
\newcommand*{\Ncols@amp}{&}
\makeatother

\begin{document}

\N=10
\begin{tabular}{|*{\N}{c|}}
\Ncols
\end{tabular}

\end{document}

結果

答案2

海子的回答解釋了您的程式碼存在的問題、如何解決該問題,以及如何使用可擴展整數循環以不同的方式進行操作(感謝\numexpr)。

A.埃萊特的回答pgffor使用和提供了另外兩個解決方案pgfkeys

DJP的回答是一種使用外部工具的方法,這裡由強大的viaPython code處理。Sagesagetex

這些答案都需要以一種或另一種形式進行一些額外的工作,例如(對於那些TeX)將表格隱藏&在巨集中,或使用 進行全域定義\xdef,或準備令牌清單暫存器,或使用各種TeX條件。

xintFor從包中構建新工具是一種替代方案(參見如何迭代逗號分隔的清單?)這樣就省去了額外編碼的麻煩:

\documentclass{article}
\usepackage{xinttools}
\newcommand{\N}{10}
\begin{document}
% \renewcommand{\N}{<nb of cols>}
\begin{tabular}{*{\N}c}
  \xintFor* #1 in {\xintSeq {1}{\N}}\do {\xintifForFirst{}{&}#1}\\
\end{tabular}
\end{document}

動態表格

測試\xintifForFirst{YES}{N0}是僅在給定行的第二個和下一個儲存格中插入表格&(此處僅一行)。此 \xintSeq巨集產生整數的算術序列(例如{1}{2}{3}{4})。迭代\xintFor* #1 in它的參數(它的未加星號的表兄弟\xintFor迭代一個逗號分隔的列表),令#1其中的每一項接一個。

與上面相同的程式碼,但使用了一個LaTeX計數器:

\documentclass{article}
\usepackage{xinttools}
\newcounter{N}
\begin{document}
\setcounter{N}{10}
\begin{tabular}{*{\value{N}}c}
  \xintFor* #1 in {\xintSeq {1}{\value{N}}}\do {\xintifForFirst{}{&}#1}\\
\end{tabular}
\end{document}

現在這是一個更詳細的範例(因為它使用兩個巢狀循環),它會建構乘法表:\numexpr用於行索引與列索引的乘法。

動態表格2

這是代碼:

\documentclass{article}
\usepackage{xinttools}

\newcommand\MultTable [4]{% 
  % #1, #2 row indices
  % #3, #4 column indices: we need #4-#3+2 columns
  \begin{tabular}{*{\numexpr#4-#3+2\relax}c}
  \hline
  % headerline
  $\times$\xintFor* ##1 in {\xintSeq {#3}{#4}}\do{&\textbf{##1}}\\
  \hline
  % #2-#1+1 rows, ##1=dynamic index of each row, ##2 column index
  \xintFor* ##1 in {\xintSeq {#1}{#2}}\do
     {\textbf{##1}
      \xintFor* ##2 in {\xintSeq {#3}{#4}}\do{&\the\numexpr ##1*##2\relax}
      \\
     }
  \hline
  \end{tabular}%
% efficiency note: one could do \edef\columnindices {\xintSeq {#3}{#4}}
% before the tabular
% and use \columnindices rather \xintSeq {#3}{#4} to avoid it being
% re-computed for each row
}

\begin{document}
\begin{table}[!htbp]
  \centering
  \MultTable {1}{10}{1}{10}
  \caption{Multiplication table}
\end{table}
\begin{table}[!htbp]
  \centering
  \MultTable {123}{132}{91}{98}
  \caption{Multiplication table}
\end{table}
\end{document}

當我們\xintFor*在使用者命令的定義中使用時LaTeX,我們需要加倍#以避免##1循環的 和#1命​​令的第一個參數之間的混淆。

答案3

如果你不介意學一點Python,這個sagetex套件可以輕鬆處理動態表;畢竟Python是一門強大的語言。 sagetex 的文檔是這裡在 example.pdf 中,他們建構了帕斯卡三角形。這是更接近您要求的代碼;第一行是 1 到 N:

\documentclass{article}
\usepackage{sagetex}
\pagestyle{empty}
\begin{document}
\begin{sagesilent}
N = 5
M = 4
output = r"\begin{tabular}{"
for i in range(0,N):
    output += r"|c"
output += r"|}"
for j in range(0,M):
    for i in range(0,N-1):
        output += r"%d & "%((j+1)*(i+1))
    output += r"%d \\"%(N*(j+1))
output += r"\end{tabular}"
\end{sagesilent}
Here's the output:\\\\
\sagestr{output}
\end{document}

在此輸入影像描述

由於您需要學習的 Python 數量有限,我想它可能比在 TeX 中編程更容易。您需要知道:for 循環不包括範圍中列出的最後一個值,而 r 用於原始字串,可以避免字串中包含反斜線等字元可能引起的問題。最後,%d 用於插入整數,%f 用於插入浮點數,%s 用於插入字串。環境sagesilent正在排版實際代碼,然後通過sagestr.

答案4

正如評論和其他答案已經建議的那樣,這可以透過多種方式來完成。這是使用pgffor和 的兩個解決方案pgfkeys

第一個解決方案無需使用密鑰即可運作:

\documentclass{article}
\usepackage{pgffor}
\usepackage{etoolbox}

\makeatletter
\newcommand\aeDynamicTable{\ae@dynamicTable}
\def\ae@dynamicTable[#1]#2{%%
  \let\ae@table@content\relax%%
  \def\ae@new@column{&}
  \def\ae@row{0}%%
  \foreach \x in {1,...,#2}
    {%%
      \xdef\ae@row{\number\numexpr\ae@row+1\relax}%%
      \ifx\relax\ae@table@content
        \xdef\ae@table@content{\noexpand\@arabic{\x}}%
      \else
        \xdef\ae@table@content{\expandonce{\ae@table@content} \noexpand\@arabic{\x}}%%
      \fi
      \ifnum\ae@row=#1\relax
        \xdef\ae@row{0}%%
        \def\ae@new@line{\\}%%
        \def\ae@new@column{}%%
      \else
        \def\ae@new@line{}%%
        \def\ae@new@column{&}%%
      \fi
      \ifnum\x=#2\relax
        \def\ae@new@line{}%%
        \def\ae@new@column{}%%
      \fi
      \xdef\ae@table@content{\expandonce{\ae@table@content} \expandonce{\ae@new@column} \expandonce{\ae@new@line}}%
    }%%
    \begin{tabular}{|*{#1}{c|}}
      \ae@table@content 
    \end{tabular}%%
  }

\makeatother

\begin{document}

\aeDynamicTable[3]{5}

\aeDynamicTable[10]{35}

\end{document}

第二個範例使用鍵完成相同的任務:

\documentclass{article}
\usepackage{pgffor}
\usepackage{pgfkeys}
\usepackage{etoolbox}

\makeatletter
\def\ae@col@limit{}
\def\ae@max@cells{}
\pgfkeys{/ae/dynamic/table/.cd,
  cols/.store in=\ae@col@limit,
  cells/.store in=\ae@max@cells,
}

\newcommand\aeDynamicTable{\ae@dynamicTable}
\def\ae@dynamicTable#1{%%
  \pgfkeys{/ae/dynamic/table/.cd,#1}%% 
  \let\ae@table@content\relax%%
  \def\ae@new@column{&}
  \def\ae@col{0}%%
  \foreach \x in {1,...,\ae@max@cells}
    {%%
      \xdef\ae@col{\number\numexpr\ae@col+1\relax}%%
      \ifx\relax\ae@table@content
        \xdef\ae@table@content{\noexpand\@arabic{\x}}%
      \else
        \xdef\ae@table@content{\expandonce{\ae@table@content} \noexpand\@arabic{\x}}%%
      \fi
      \ifnum\ae@col=\ae@col@limit\relax
        \xdef\ae@col{0}%%
        \def\ae@new@line{\\}%%
        \def\ae@new@column{}%%
      \else
        \def\ae@new@line{}%%
        \def\ae@new@column{&}%%
      \fi
      \ifnum\x=\ae@max@cells\relax
        \def\ae@new@line{}%%
        \def\ae@new@column{}%%
      \fi
      \xdef\ae@table@content{\expandonce{\ae@table@content} \expandonce{\ae@new@column} \expandonce{\ae@new@line}}%
    }%%
    \begin{tabular}{|*{\ae@col@limit}{c|}}
      \ae@table@content 
    \end{tabular}%%
  }

\makeatother

\begin{document}

\aeDynamicTable{cols=3,cells=5}

\aeDynamicTable{cols=10,cells=35}

\end{document}

無論哪種情況,結果表都是:

在此輸入影像描述

相關內容