
動的なデータを入力しながら表を動的に生成するにはどうすればよいですか?
例: 私が
\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 が含まれる 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
と を使用したさらに 2 つのソリューションを提供しますpgfkeys
。
DJPの回答は外部ツールを使用する方法であり、ここでPython code
は強力なSage
viaによって処理されますsagetex
。
これらの回答はすべて、何らかの形で追加の作業を必要とします。たとえば、(回答者の場合)マクロ内のTeX
タブを非表示にしたり、 を使用してグローバル定義を行ったり、トークン リスト レジスタを準備したり、さまざまな種類の条件を使用したりします。&
\xdef
TeX
xintFor
パッケージからの構築xintツール代替案としては(カンマ区切りのリストを反復処理するにはどうすればいいですか?) を使用すると、余分なコーディングの手間が省けます。
\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}
テストでは、指定された行 (ここでは 1 行のみ) の 2 番目と次のセルにのみ \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}
ここでは、乗算表を作成するより複雑な例 (2 つのネストされたループを使用) を示します。これは、\numexpr
行インデックスと列インデックスの乗算に使用されます。
コードは次のとおりです:
\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
を 2 倍にする必要がありました。#
##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
と を使用した 2 つのソリューションを次に示します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}
この 2 番目の例では、キーを使用して同じタスクを実行します。
\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}
どちらの場合も、結果の表は次のようになります。