如何从数组中获取数值

如何从数组中获取数值

我正在努力使用该包从数组中获取数值arrayjobx。我的目标是将值列表存储在几个数组中,然后在表中显示它们时能够显示总和(每行/列)。我会使用计数器来计算总和,但我无法获取存储在中的数值,array以便用它来\addtocounter计算总和。

以下是一个简短的例子:

\documentclass{letter}
\usepackage{arrayjobx}

\begin{document}

\newarray\First
\newarray\Second
\newarray\Third 
\readarray{First}{10&8&3}
\readarray{Second}{1&7&8} 
\readarray{Third}{1&5&16}
\newcounter{ExpOneTotal}

\begin{tabular}{|c|c|c|c|c|}
\hline
Experiment & a & b & c & TOTAL \\ \hline 
Exp 1 & \First(1) & \First(2) & \First(3) &  \\ 
Exp 2 & \Second(1) & \Second(2) & \Second(3)  & \\ 
Exp 3 & \Third(1) & \Third(2) & \Third(3) & \\ 
TOTAL & & & & \\ 
\hline 
\end{tabular}

\First(1)

\the\numexpr \First(1) \relax 

\addtocounter{ExpOneTotal}{\numexpr \First(1) \relax}

My counter is: \theExpOneTotal~ instead of \First(1)

\end{document}

在此处输入图片描述

答案1

您可以使用更灵活的方法;arrayjobx没有必要那么复杂,而且expl3方法更加强大。

\documentclass{letter}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\setarray}{O{;}mm}
 {
  \seq_clear_new:c { g_alexb_array_#2_seq }
  \seq_gset_split:cnn { g_alexb_array_#2_seq } { #1 } { #3 }
 }
\NewDocumentCommand{\getfromarray}{mm}
 {
  \seq_item:cn { g_alexb_array_#1_seq } { #2 }
 }
\cs_generate_variant:Nn \seq_gset_split:Nnn { c }
\cs_set_eq:NN \inteval \int_eval:n
\ExplSyntaxOff

\newcounter{ExpOneTotal}

\begin{document}

\setarray{First}{10;8;3}
\setarray{Second}{1;7;8} 
\setarray{Third}{1;5;16}

\begin{tabular}{|c|c|c|c|c|}
\hline
Experiment & a & b & c & TOTAL \\ \hline 
Exp 1 & \getfromarray{First}{1} & \getfromarray{First}{2} & \getfromarray{First}{3} &  \\ 
Exp 2 & \getfromarray{Second}{1} & \getfromarray{Second}{2} & \getfromarray{Second}{3}  & \\ 
Exp 3 & \getfromarray{Third}{1} & \getfromarray{Third}{2} & \getfromarray{Third}{3} & \\ 
TOTAL & & & & \\ 
\hline 
\end{tabular}

\getfromarray{First}{1}

\the\numexpr \getfromarray{First}{1} \relax 

\addtocounter{ExpOneTotal}{\numexpr \getfromarray{First}{1} \relax}

My counter is \theExpOneTotal{}; should be \getfromarray{First}{1}.

\setcounter{ExpOneTotal}{%
  \inteval{
   \getfromarray{First}{1}+
   \getfromarray{Second}{1}+
   \getfromarray{Third}{1}
  }
}

My counter is \theExpOneTotal{}; should be
  \inteval{
   \getfromarray{First}{1}+
   \getfromarray{Second}{1}+
   \getfromarray{Third}{1}
  }

\end{document}

如您所见,\inteval您甚至不需要设置计数器,因为可以即时进行计算。

\setarray命令中,分隔符是可自定义的,您可以执行

\setarray[&]{First}{10&8&3}

如果您愿意的话(甚至可以将标记更改为O参数的默认值)。

在此处输入图片描述

您甚至可以使用浮点值,而不是\fpeval\inteval需要加载xfp包)。

答案2

\First不可扩展,因此不能在中使用\numexpr。包arrayjobx提供以下替代方案:

\check<arrayname>提取所需的值并将其存储在现在可以在其他地方\cachedata使用:\numexpr

\documentclass{letter}
\usepackage{arrayjobx}

\begin{document}

\newarray\First
\readarray{First}{10&8&3}
\newcounter{ExpOneTotal}

\First(1)

\checkFirst(1)\cachedata~=~\the\numexpr\cachedata\relax

\addtocounter{ExpOneTotal}{\cachedata}

My counter is: \theExpOneTotal~=~\First(1)

\end{document}

结果

计算行和列的总和:

\documentclass{letter}
\usepackage{arrayjobx}
\usepackage{booktabs}

\begin{document}

\newarray\First
\newarray\Second
\newarray\Third 
\readarray{First}{10&8&3}
\readarray{Second}{1&7&8} 
\readarray{Third}{1&5&16}
\newcounter{ExpTotali}
\newcounter{ExpTotalii}
\newcounter{ExpTotaliii}

\def\AddTotal#1(#2){%
  \csname check#1\endcsname({#2})%
  \cachedata
  \addtocounter{ExpTotal\romannumeral#2}\cachedata
}

\newcounter{ExpTotalSum}
\newcounter{ExpSum}
\makeatletter
\def\ExpSum#1(#2){%
  \setcounter{ExpSum}{0}%
  \begingroup
    \@for\I:=#2\do{%
      \csname check#1\endcsname(\I)%
      \addtocounter{ExpSum}{\cachedata}%
    }%
  \endgroup
  \theExpSum
  \addtocounter{ExpTotalSum}{\value{ExpSum}}%
}
\makeatother

\begin{tabular}{ccccc}
\toprule
Experiment & a & b & c & TOTAL \\
\midrule
Exp 1 & \AddTotal{First}(1) & \AddTotal{First}(2) & \AddTotal{First}(3) &
  \ExpSum{First}(1,2,3) \\ 
Exp 2 & \AddTotal{Second}(1) & \AddTotal{Second}(2) & \AddTotal{Second}(3) &
  \ExpSum{Second}(1,2,3) \\ 
Exp 3 & \AddTotal{Third}(1) & \AddTotal{Third}(2) & \AddTotal{Third}(3) &
  \ExpSum{Third}(1,2,3) \\ 
\midrule
TOTAL & \theExpTotali & \theExpTotalii & \theExpTotaliii &
  \theExpTotalSum \\ 
\bottomrule
\end{tabular}
\end{document}

结果表

通过包对数字进行对齐siunitx

\documentclass{letter}
\usepackage{arrayjobx}
\usepackage{booktabs}
\usepackage{siunitx}

\begin{document}

\newarray\First
\newarray\Second
\newarray\Third 
\readarray{First}{10&8&3}
\readarray{Second}{1&7&8} 
\readarray{Third}{1&5&16}
\newcounter{ExpTotali}
\newcounter{ExpTotalii}
\newcounter{ExpTotaliii}

\def\AddTotal#1(#2){%
  \csname check#1\endcsname({#2})%
  \addtocounter{ExpTotal\romannumeral#2}\cachedata
  \global\let\CD\cachedata
}

\newcounter{ExpTotalSum}
\newcounter{ExpSum}
\makeatletter
\def\ExpSum#1(#2){%
  \setcounter{ExpSum}{0}%
  \begingroup
    \@for\I:=#2\do{%
      \csname check#1\endcsname(\I)%
      \addtocounter{ExpSum}{\cachedata}%
    }%
  \endgroup
  \addtocounter{ExpTotalSum}{\value{ExpSum}}%
}
\makeatother

\begin{tabular}{c*{4}{S[table-format=2]}}
\toprule
Experiment & a & b & c & TOTAL \\
\midrule
Exp 1
  & {\AddTotal{First}(1)}\CD
  & {\AddTotal{First}(2)}\CD
  & {\AddTotal{First}(3)}\CD
  & {\ExpSum{First}(1,2,3)}\theExpSum \\ 
Exp 2
  & {\AddTotal{Second}(1)}\CD
  & {\AddTotal{Second}(2)}\CD
  & {\AddTotal{Second}(3)}\CD
  & {\ExpSum{Second}(1,2,3)}\theExpSum \\
Exp 3
  & {\AddTotal{Third}(1)}\CD
  & {\AddTotal{Third}(2)}\CD
  & {\AddTotal{Third}(3)}\CD
  & {\ExpSum{Third}(1,2,3)}\theExpSum \\ 
\midrule
TOTAL & \theExpTotali & \theExpTotalii & \theExpTotaliii &
  \theExpTotalSum \\ 
\bottomrule
\end{tabular}
\end{document}

带对齐数字的结果表

相关内容