3

Is it possible to pass an array argument to newcommand and then access those individual array elements?

For example, if I wanted to multiply the third element of the array (first argument) by the value of the second argument:

\newcommand{\hello}[2]{(#1.#3)*#2}

(Note #1.#3 is probably incorrect, I'm asking how to access this value.)

And using the command in the body code:

I want \hello{1,2,5}{2} gumdrops.

Edit: minimum working example?

\documentclass{standalone}
\newcommand{\hello}[2]{(#1)*(#2)}
\begin{document}
I want \hello{1}{2} gumdrops.
\end{document}

It's not really multiplying (I guess I don't know how to multiply numbers in newcommand), but that's not important to me and either way I want to be able to access the values of the arguments. Except in the first argument I'd like to be able to pass an array and access each specific element of it individually (i.e. not looping over it), which is totally not expressed in the MWE.

  • 1
    Yes. If your array argument implies using a comma-separated list, then you can iterate over the elements by following the guidelines in How to iterate over a comma separated list? – Werner Feb 17 '15 at 20:47
  • Thanks. I'm having a hard time reading that (I don't code much low-level LaTeX) but most of them don't seem to be accessing the actual individual elements and are just iterating over the list. I'm looking more to access the individual elements. The one thing I noticed was some ##1, which I'm not sure what that is but maybe that's what I want? – Hanmyo Feb 17 '15 at 20:55
  • Then you need to describe your use-case better. For example, \hello{A,2,c} creates a structure (an "array") with three elements, say. And you want to access \hello{1} as being the first element (returning A), \hello{2} returning 2 and \hello{3} returning c. Do you want to manipulate the elements after creating them as well, or just retrieve them? – Werner Feb 17 '15 at 21:03
  • I want to access them so that I can use them in calculations. Sorry I was unclear. I will change my question to be a bit more clear. – Hanmyo Feb 17 '15 at 21:14
  • I'm tempted to suggest a different user interface: \newarray{myarray}{1,2,3} and then use \getelement{myarray}{3}*2 or \getlastelement{myarray}*2. It would generalize your question since tomorrow you're going to be interested in performing some calculation on element 2, or some random element, for which "last element extraction" might not be general enough. – Werner Feb 17 '15 at 21:21
2

The following might suit you:

enter image description here

\documentclass{article}
\usepackage{etoolbox,xparse}

\ExplSyntaxOn
  \cs_new_eq:NN \CALC \fp_eval:n
\ExplSyntaxOff

\newcounter{argcnt}
\makeatletter
\newcommand{\newarray}[2]{% \newarray{<array>}{<csv list>}
  \setcounter{argcnt}{0}% Restart argument count
  \renewcommand{\do}[1]{% With each element do...
    \stepcounter{argcnt}% Next arg
    \expandafter\gdef\csname #1@\theargcnt\endcsname{##1}% Store arg in \<array>@<num>
  }%
  \docsvlist{#2}% Store array
  \expandafter\xdef\csname #1@0\endcsname{\theargcnt}% Store array element count
}
\newcommand{\getelement}[2]{% \getelement{<array>}{<num>}
  \@ifundefined{#1@0}% <array> not defined
    {\@latex@error{Array #1 undefined}\@ehc}{}
  \expandafter\ifnum\csname #1@0\endcsname<#2 % <num> out of range
    \@latex@error{Array #1 only has \csname #1@0\endcsname\space elements}\@ehc
  \fi
  \csname #1@#2\endcsname% Print element
}
\newcommand{\calc}[1]{\expandafter\CALC\expandafter{#1}}% calculations
\makeatother

\begin{document}
\newarray{arrayA}{a,b,c}%
\newarray{arrayB}{1,2,3}%

\getelement{arrayA}{1}

$2 \times \getelement{arrayB}{2} + \getelement{arrayB}{3} = \calc{2*\getelement{arrayB}{2}+\getelement{arrayB}{3}}$
\end{document}

\newarray{<array>}{<csv list>} creates the array <array> with elements contained within the comma-separated value list <csv list>. \getelement{<array>}{<num>} acts like an array indexing, while \calc can be used to perform calculations on numeric elements.

The approach allows you to store virtually anything in the array, rather than just numbers (and/or mix them).

1

Is this something like what you mean? Perhaps this could get you started.

\documentclass{article}

\newcommand{\twothings}[2]{%
    \gdef\thingone{#1}
    \gdef\thingtwo{#2}
}

\newcommand{\pickone}[1]{%
    \ifnum#1 = 1
        \thingone
    \else
        \ifnum#1 = 2
            \thingtwo
        \else
            \relax
        \fi
    \fi%
}

\begin{document}

\twothings{First}{Second}

The second thing is \pickone{2}.

\end{document}
  • Sorry, that's not really what I'm looking for. I think you meant \pickone{1}{2} in your code, but I really wanted to pass an array/list type argument and grab the elements. This one just passes two separate elements and looks at them. – Hanmyo Feb 18 '15 at 8:21
  • Actually I meant \newcommand{\pickone}[1] and then #1 for the arguments in the code, since there was only one argument. I edited the answer. – musarithmia Feb 18 '15 at 12:22
  • In TeX a control sequence expands to a single definition (e.g., \def\array{data}), so there are not multiple elements to access. Instead you have to make an array manually by creating a series of control sequences with sequential keys in their names (using an \expandafter trick you define \array1{data1}, \array2{data2}, etc.). Then you can access the contents of specific "array elements" by calling the control sequence you desire (\array2). @Werner shows a good way to do this. – musarithmia Feb 18 '15 at 12:26
  • Just to be clear about arguments, in TeX you define a command that takes multiple arguments like this: \def\command #1#2{#1#2}. In LaTeX you do this: \newcommand{\command}[2]{#1#2}. In both examples \command expands to a string that is the combination of both arguments passed to it, so \command{book}{keeping} is typeset as bookkeeping. In normal commands there is no way to access the arguments separately from the command. In my answer I showed how to make a command that defined two control sequences which you could then access separately. This is like a miniature array, I suppose. – musarithmia Feb 18 '15 at 12:31

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.