4

I'm struggling to get the numeric value out from arrays using the arrayjobx package. My goal is to store a list of values in several arrays, then when display them in a table be able to show the sum (per row / column). I would use a counter to calculate the sum, but I'm not managing to get out the numeric value stored in the array, to use it in \addtocounter to calculate the sum.

Here is a short example:

\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}

enter image description here

4

You can use more flexible methods; arrayjobx is unnecessarily complex and expl3 methods are much more powerful.

\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}

As you see, with \inteval you don't even need to set up a counter, because the computation can be done on the fly.

In the \setarray command the delimiter is customizable, you can do

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

if you prefer (or even change the token for the default value of the O argument).

enter image description here

You can even use floating point values, using \fpeval instead of \inteval (requires loading the xfp package).

4

\First is not expandable and can therefore not be used in \numexpr. The package arrayjobx provides the following alternative:

\check<arrayname> extracts the desired value and stores it in \cachedata that can now be used in \numexpr and other places:

\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}

Result

With calculations of row and column sums:

\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}

Result table

With alignment of the numbers via package 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}

Result table with aligned numbers

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.