
동적 데이터로 채우면서 테이블 형식을 동적으로 생성하려면 어떻게 해야 합니까?
예: 내가 가지고 있다고 가정해보자
\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.Ellett의 답변pgffor
및 를 사용하여 두 가지 솔루션을 더 제공합니다 pgfkeys
.
DJP의 답변는 외부 도구를 사용하는 방법으로, 여기서는 Python code
강력한 Sage
via 에 의해 처리됩니다 sagetex
.
이러한 답변은 모두 매크로에서 TeX
표를 숨기거나 전역 정의를 수행하거나 토큰 목록 레지스터를 준비하거나 다양한 종류의 조건을 사용하는 등의 추가 작업이 어떤 형태로든 필요합니다 .&
\xdef
TeX
xintFor
패키지의 구성xinttools대안입니다 (참조쉼표로 구분된 목록을 반복하는 방법은 무엇입니까?) 이는 추가 코딩의 문제를 줄여줍니다.
\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
행 인덱스와 열 인덱스의 곱셈에 사용됩니다.
코드는 다음과 같습니다.
\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}
두 경우 모두 결과 테이블은 다음과 같습니다.