根据 egreg 对我的第一个问题的回答(再次感谢他) 这里,我尝试了以下方法在水平和垂直函数表之间切换。这似乎工作正常(脏代码)。但在水平模式下,我必须在 #4 处的宏 \functiontabT 中给出列表中的值的数量。
我的问题是,如何自动计算值的数量并用它来创建表中的列数。
感谢您的帮助
\documentclass{article}
\usepackage{xparse}
\usepackage{xintexpr}
\usepackage{siunitx}
\ExplSyntaxOn
\NewDocumentCommand{\functiontableV}{mmO{2}}
{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontable:nnn { #1 } { #2 } { #3 }
}
\seq_new:N \__thomas_functiontable_rows_seq
\cs_new_protected:Nn \thomas_functiontable:nnn
{
\cs_set:Nn \__thomas_functiontable_function:n { #2 }
\seq_clear:N \l__thomas_functiontable_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontable_rows_seq
{
\num{ ##1 } & \num{ \fp_eval:n { round( \__thomas_functiontable_function:n { ##1 }, #3 ) } }
}
}
\seq_use:Nn \l__thomas_functiontable_rows_seq { \\ }
}
\ExplSyntaxOff
\ExplSyntaxOn
\NewDocumentCommand{\functiontab}{mmO{2}}{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontab:nnn { #1 } { #2 } { #3 } }
\seq_new:N \__thomas_functiontab_rows_seq
\cs_new_protected:Nn \thomas_functiontab:nnn
{
\cs_set:Nn \__thomas_functiontab_function:n { #2 }
\seq_clear:N \l__thomas_functiontab_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontab_rows_seq
{
& \num{ ##1 }
}
}
\seq_use:Nn \l__thomas_functiontab_rows_seq {}
}
\NewDocumentCommand{\functiontabB}{mmO{2}}{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontabB:nnn { #1 } { #2 } { #3 } }
\seq_new:N \__thomas_functiontabB_rows_seq
\cs_new_protected:Nn \thomas_functiontabB:nnn
{
\cs_set:Nn \__thomas_functiontabB_function:n { #2 }
\seq_clear:N \l__thomas_functiontabB_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontabB_rows_seq
{
& \num{ \fp_eval:n { round( \__thomas_functiontabB_function:n { ##1 }, #3 ) } }
}
}
\seq_use:Nn \l__thomas_functiontabB_rows_seq {}
}
\ExplSyntaxOff
\NewDocumentCommand{\functiontabT}{mmO{2}mmmO{$x$}D(){$f(x)$}t{!}}{%% #1 = list of values, #2 = function, #3 = number of decimal digits
% #4 = Number of columns, #5 = width column 1, #6 = width column 2 and all others in horizontal, #7 = name x, #8 = name f(x), #9 = ! switch horizontal - vertical
\IfBooleanTF{#9}{%
\begin{tabular}{>{\centering\arraybackslash}p{#5}|>{\centering\arraybackslash}p{#6}}
{#7} & {#8} \\\hline
\functiontableV{#1}{#2}[#3]
\end{tabular}
}{%
\begin{tabular}{>{\centering\arraybackslash}p{#5}*{#4}{|>{\centering\arraybackslash}p{#6}}}
#7 \functiontab{#1}{#2}[#3] \\ \hline
#8 \functiontabB{#1}{#2}[#3]
\end{tabular}
}
}
\begin{document}
\functiontabT{1, 2, 3.5, 4, 6,100,200}{ ln(#1^3+13) }[2]{7}{1cm}{0.8cm}[a](b)
\bigskip
\functiontabT{1, 2, 3.5, 4,11,14,300,500}{ ln(\xinttheexpr #1! \relax) }[2]{8}{1cm}{1.4cm}!
\bigskip
\functiontabT{0, 30, 45, 60, 90}{ sind(#1) }[5]{7}{1cm}{1.6cm}!
\end{document}
答案1
这是水平表和垂直表的实现。
\documentclass{article}
\usepackage{xparse}
\usepackage{siunitx}
\usepackage{array}
\ExplSyntaxOn
\NewDocumentCommand{\functiontable}{O{}mm}
{% #1 = option list, #2 = list of values, #3 = function
\group_begin:
\keys_set:nn { thomas/functiontable } { #1 }
\bool_if:NTF \l__thomas_functiontable_hor_bool
{
\thomas_functiontable_hor:nn { #2 } { #3 }
}
{
\thomas_functiontable_vert:nn { #2 } { #3 }
}
\group_end:
}
\seq_new:N \__thomas_functiontable_rows_seq
\seq_new:N \__thomas_functiontable_row_one_seq
\seq_new:N \__thomas_functiontable_row_two_seq
\seq_new:N \l__thomas_functiontable_columns_seq
\keys_define:nn { thomas/functiontable }
{
hor .bool_set:N = \l__thomas_functiontable_hor_bool,
hor .initial:n = false,
hor .default:n = true,
round .int_set:N = \l__thomas_functiontable_round_int,
round .initial:n = 2,
ivar .tl_set:N = \l__thomas_functiontable_ivar_tl,
ivar .initial:n = x,
dvar .tl_set:N = \l__thomas_functiontable_dvar_tl,
dvar .initial:n = f(x),
align .tl_set:N = \l__thomas_functiontable_align_tl,
align .initial:n = c,
cols .tl_set:N = \l__thomas_functiontable_make_columns_tl,
}
\cs_new_protected:Nn \thomas_functiontable_vert:nn
{
\cs_set:Nn \__thomas_functiontable_function:n { #2 }
\seq_clear:N \l__thomas_functiontable_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontable_rows_seq
{
##1
&
\exp_not:N \__thomas_functiontable_num:n
{
\fp_eval:n
{
round( \__thomas_functiontable_function:n { ##1 }, \l__thomas_functiontable_round_int )
}
}
}
}
\__thomas_functiontable_make_columns_vert:
\use:x
{
\exp_not:N \begin{tabular}
[\l__thomas_functiontable_align_tl]
{\exp_not:V \l__thomas_functiontable_columns_tl}
}
$\l__thomas_functiontable_ivar_tl$ & $\l__thomas_functiontable_dvar_tl$ \\
\hline
\seq_use:Nn \l__thomas_functiontable_rows_seq { \\ }
\end{tabular}
}
\cs_new_protected:Nn \__thomas_functiontable_make_columns_vert:
{
\tl_if_in:NnTF \l__thomas_functiontable_make_columns_tl { S }
{
\cs_set_eq:NN \__thomas_functiontable_num:n \use:n
}
{
\cs_set_eq:NN \__thomas_functiontable_num:n \num
}
\tl_if_empty:NTF \l__thomas_functiontable_make_columns_tl
{
\tl_set:Nn \l__thomas_functiontable_columns_tl { c | c }
}
{
\seq_set_split:NnV \l__thomas_functiontable_columns_seq { | } \l__thomas_functiontable_make_columns_tl
\int_compare:nTF { \seq_count:N \l__thomas_functiontable_columns_seq <= 1 }
{
\tl_set:Nx \l__thomas_functiontable_columns_tl
{
\l__thomas_functiontable_make_columns_tl | \l__thomas_functiontable_make_columns_tl
}
}
{
\tl_set:Nx \l__thomas_functiontable_columns_tl
{
\seq_item:Nn \l__thomas_functiontable_columns_seq { 1 }
|
\seq_item:Nn \l__thomas_functiontable_columns_seq { 2 }
}
}
}
}
\cs_new_protected:Nn \thomas_functiontable_hor:nn
{
\cs_set:Nn \__thomas_functiontable_function:n { #2 }
\seq_clear:N \l__thomas_functiontable_row_one_seq
\seq_clear:N \l__thomas_functiontable_row_two_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nn \l__thomas_functiontable_row_one_seq { \num{##1} }
\seq_put_right:Nx \l__thomas_functiontable_row_two_seq
{
\num
{
\fp_eval:n
{
round( \__thomas_functiontable_function:n { ##1 }, \l__thomas_functiontable_round_int )
}
}
}
}
\__thomas_functiontable_make_columns_hor:
\use:x
{
\exp_not:N \begin{tabular}
[\l__thomas_functiontable_align_tl]
{\exp_not:V \l__thomas_functiontable_columns_tl}
}
$\l__thomas_functiontable_ivar_tl$ & \seq_use:Nn \l__thomas_functiontable_row_one_seq { & }
\tabularnewline
\hline
$\l__thomas_functiontable_dvar_tl$ & \seq_use:Nn \l__thomas_functiontable_row_two_seq { & }
\end{tabular}
}
\cs_new_protected:Nn \__thomas_functiontable_make_columns_hor:
{
\tl_if_empty:NTF \l__thomas_functiontable_make_columns_tl
{
\tl_set:Nx \l__thomas_functiontable_columns_tl
{
c
*{\seq_count:N \l__thomas_functiontable_row_one_seq}{|c}
}
}
{
\seq_set_split:NnV \l__thomas_functiontable_columns_seq { | } \l__thomas_functiontable_make_columns_tl
\int_compare:nTF { \seq_count:N \l__thomas_functiontable_columns_seq <= 1 }
{
\tl_set:Nx \l__thomas_functiontable_columns_tl
{
\l__thomas_functiontable_make_columns_tl
*{\seq_count:N \l__thomas_functiontable_row_one_seq}{|\l__thomas_functiontable_make_columns_tl}
}
}
{
\tl_set:Nx \l__thomas_functiontable_columns_tl
{
\seq_item:Nn \l__thomas_functiontable_columns_seq { 1 }
*{\seq_count:N \l__thomas_functiontable_row_one_seq}
{
|\seq_item:Nn \l__thomas_functiontable_columns_seq { 2 }
}
}
}
}
}
\ExplSyntaxOff
\begin{document}
X \functiontable[hor]{1, 2, 3.5, 4}{ #1^2+3 } Y
\bigskip
X \functiontable[hor,cols=c|>{\centering}p{2cm}]{1, 2, 3.5, 4}{ #1^2+3 } Y
\bigskip
X \functiontable[
round=5,
ivar=a,
dvar=b,
align=t,
cols={ S[table-format=2.0] | S[table-format=1.5] },
]{0, 30, 45, 60, 90}{ sind(#1) } Y
\end{document}
答案2
我发现
\clist_count:n { #1 }
这个有效。
\documentclass{article}
\usepackage{xparse}
\usepackage{xintexpr}
\usepackage{siunitx}
\sisetup{group-separator={\,},output-decimal-marker={,}}
\ExplSyntaxOn
\NewDocumentCommand{\functiontableV}{mmO{2}}
{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontable:nnn { #1 } { #2 } { #3 }
}
\seq_new:N \__thomas_functiontable_rows_seq
\cs_new_protected:Nn \thomas_functiontable:nnn
{
\cs_set:Nn \__thomas_functiontable_function:n { #2 }
\seq_clear:N \l__thomas_functiontable_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontable_rows_seq
{
\num{ ##1 } & \num{ \fp_eval:n { round( \__thomas_functiontable_function:n { ##1 }, #3 ) } }
}
}
\seq_use:Nn \l__thomas_functiontable_rows_seq { \\ }
}
\NewDocumentCommand{\functiontab}{mmO{2}}{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontab:nnn { #1 } { #2 } { #3 } }
\seq_new:N \__thomas_functiontab_rows_seq
\cs_new_protected:Nn \thomas_functiontab:nnn
{
\cs_set:Nn \__thomas_functiontab_function:n { #2 }
\seq_clear:N \l__thomas_functiontab_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontab_rows_seq
{
& \num{ ##1 }
}
}
\seq_use:Nn \l__thomas_functiontab_rows_seq {}
}
\NewDocumentCommand{\functiontabB}{mmO{2}}{% #1 = list of values, #2 = function, #3 = number of decimal digits
\thomas_functiontabB:nnn { #1 } { #2 } { #3 } }
\seq_new:N \__thomas_functiontabB_rows_seq
\cs_new_protected:Nn \thomas_functiontabB:nnn
{
\def\AnzahlderElemente{\clist_count:n { #1 }}
\cs_set:Nn \__thomas_functiontabB_function:n { #2 }
\seq_clear:N \l__thomas_functiontabB_rows_seq
\clist_map_inline:nn { #1 }
{
\seq_put_right:Nx \l__thomas_functiontabB_rows_seq
{
& \num{ \fp_eval:n { round( \__thomas_functiontabB_function:n { ##1 }, #3 ) } }
}
}
\seq_use:Nn \l__thomas_functiontabB_rows_seq {}
}
\NewDocumentCommand{\functiontabT}{mmO{2}mmO{$x$}D(){$f(x)$}t{!}}{%% #1 = list of values, #2 = function, #3 = number of decimal digits
% #4 = width column 1, #5 = width column 2 and all others in horizontal, #6 = name x, #7 = name f(x), #8 = ! switch horizontal - vertical
\IfBooleanTF{#8}{%
\begin{tabular}{>{\centering\arraybackslash}p{#4}|>{\centering\arraybackslash}p{#5}}
{#6} & {#7} \\\hline
\functiontableV{#1}{#2}[#3]
\end{tabular}
}{%
\begin{tabular}{>{\centering\arraybackslash}p{#4}*{\clist_count:n { #1 }}{|>{\centering\arraybackslash}p{#5}}}
#6 \functiontab{#1}{#2}[#3] \\ \hline
#7 \functiontabB{#1}{#2}[#3]
\end{tabular}
}
}
\ExplSyntaxOff
\begin{document}
\functiontabT{1, 2, 3.5, 4, 6,100,200,300,30}{ ln(#1^3+13) }[2]{1cm}{0.8cm}[a](b)
\bigskip
\functiontabT{1, 2, 3.5, 4,11,14,300,500}{ ln(\xinttheexpr #1! \relax) }[2]{1cm}{1.4cm}!
\bigskip
\functiontabT{0, 30, 45, 60, 90}{ sind(#1) }[5]{0.8cm}{1.3cm}
\end{document}