0

I defined an array that contains 4 integers. I accessed the 3rd element, modified the last element then accessed it. However instead of doing array operations latex simply replaces every instance of \array with the entire array . How should I modify my code so that it works as expected?

\documentclass{article}
\usepackage{tikz}
\begin{document}

\edef\array{5,12,13,14}

\array{2} \ \array{3}=5 \ \array{3} \end{document}

Expected:

13
5

Reality:

5,12,13,142
5,12,13,143=5
5,12,13,143
Qrrbrbirlbel
  • 119,821
  • 3
    tex does not have arrays (or integer literals) \edef\array{5,12,13,14} defines \array (a really bad name as it breaks \begin{array}... ) to be the 10 tokens 5 , 1 2 , 1 3 , 1 4 – David Carlisle Oct 21 '22 at 07:56
  • 1
    using a macro that allows indexed entry to a comma list is easy enough, latex has some pre-defined, see clist module in texdoc interface3 but supporting an assignment syntax like \array{3}=5 is possible but a lot more complicated and probably not needed compared to say \setarray{3}{5} but you should probably describe your use case and how you want to use this before anyone can suggest a replacement – David Carlisle Oct 21 '22 at 08:10
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Oct 21 '22 at 08:30
  • Some clarifications: The array functionality you get when you load TikZ is the one that comes from PGFmath. It has very limited functionality and there's no in-built way to change one specific value in an array. – Qrrbrbirlbel Oct 21 '22 at 09:03
  • The math library might help you to do what you want. What are you trying to do? – Qrrbrbirlbel Oct 21 '22 at 09:10
  • Somewhat related: https://tex.stackexchange.com/questions/273037/expandable-quick-sort-array-macro/273476?r=SearchResults&s=1%7C26.7054#273476 – John Kormylo Oct 21 '22 at 18:06

2 Answers2

5

You can do

\def\foo{5,12,13,14}

but this won't magically provide you some array. In some scripting languages, the value which a variable is assigned to can also type the same variable. But TeX has just macros and registers and the code above just defines a macro that takes no argument.

Note that I changed your \array to \foo because \array is predefined in LaTeX and is a really, really important command for math constructions.

If you type in \foo{2}, TeX will just typeset

5,12,13,142

because that's the way it works: the macro \foo is expanded and the replacement text is simply put in the input stream.

Just because something is done some way in Perl doesn't mean that the same would work in Python. TeX language is even funnier than Perl and Python to program in.

Do you want to emulate arrays in LaTeX? Allocating, setting and changing their values? That's surely possible.

\documentclass{article}

\ExplSyntaxOn

%%% User interface \NewDocumentCommand{\newarray}{m} { \nver_array_new:n { #1 } }

\NewDocumentCommand{\setarray}{mom} { \IfNoValueTF { #2 } { \nver_array_set:nn { #1 } { #3 } } { \nver_array_change:nnn { #1 } { #2 } { #3 } } }

\NewExpandableDocumentCommand{\getfromarray}{mm} { \nver_array_get:nn { #1 } { #2 } }

\NewExpandableDocumentCommand{\lengthofarray}{m} { \nver_array_length:n { #1 } }

%%% Public functions \cs_new_protected:Nn \nver_array_new:n { \seq_new:c { l__nver_array_#1_seq } }

\cs_new_protected:Nn \nver_array_set:nn { \seq_set_split:cnn { l__nver_array_#1_seq } { , } { #2 } } \cs_generate_variant:Nn \seq_set_split:Nnn { c }

\cs_new_protected:Nn \nver_array_change:nnn { \int_compare:nTF { \seq_count:c { l__nver_array_#1_seq } < #2 } {% we need to add empty items __nver_array_append:nnn { #1 } { #2 } { #3 } } {% we need to change a value __nver_array_change:nnn { #1 } { #2 } { #3 } } }

\cs_new:Nn \nver_array_get:nn { \seq_item:cn { l__nver_array_#1_seq } { #2 } }

\cs_new:Nn \nver_array_length:n { \seq_count:c { l__nver_array_#1_seq } }

%%% Private functions and variables

\seq_new:N \l__nver_array_in_seq \seq_new:N \l__nver_array_out_seq

\cs_new_protected:Nn __nver_array_append:nnn { \int_step_inline:nnn { \seq_count:c { l__nver_array_#1_seq } + 1 } % start from the end { #2 - 1 } % just before the index { \seq_put_right:cn { l__nver_array_#1_seq } {} } % add empty items % now we can add the new item \seq_put_right:cn { l__nver_array_#1_seq } { #3 } }

\cs_new_protected:Nn __nver_array_change:nnn {% we need to change a value \seq_set_eq:Nc \l__nver_array_in_seq { l__nver_array_#1_seq } \seq_clear:N \l__nver_array_out_seq \int_step_inline:nn { \seq_count:N \l__nver_array_in_seq } { \int_compare:nTF { ##1 = #2 } {% the item we want to change \seq_put_right:Nn \l__nver_array_out_seq { #3 } } {% copy the existing value \seq_put_right:Nx \l__nver_array_out_seq { \seq_item:Nn \l__nver_array_in_seq { ##1 } } } } \seq_set_eq:cN { l__nver_array_#1_seq } \l__nver_array_out_seq }

\ExplSyntaxOff

\begin{document}

\newarray{foo} \setarray{foo}{3,12,13,14}

Second item in \texttt{foo} is ``\getfromarray{foo}{2}''

\setarray{foo}[2]{5} % change the value of the second item

Second item in \texttt{foo} is ``\getfromarray{foo}{2}''

The array \texttt{foo} has \lengthofarray{foo} items

\setarray{foo}[10]{Tenth item!}

Tenth item in \texttt{foo} is ``\getfromarray{foo}{10}''

The array \texttt{foo} has \lengthofarray{foo} items

\end{document}

The optional argument in \setarray tells TeX that an item has to be changed. Additional empty items are inserted if the index is greater than the length of the array at the time of the call.

enter image description here

egreg
  • 1,121,712
0

If you want to use a TiKZ array, you should define it with two braces. Once defined you can acces to the elements for reading, but I don't know how to change its value:

Note: egreg advertised that using \array is a dangerous idea, so I've changed to \myarray. Also Ulrike Fischer advertised about def and it was changed to \newcommand

\documentclass{article}
\usepackage{tikz}
\begin{document}

\newcommand\myarray{{5,12,13,14}}

\pgfmathparse{\myarray[2]}\pgfmathresult \ %\array[3]=5 \ \pgfmathparse{\myarray[0]}\pgfmathresult \ \end{document}

enter image description here

Ignasi
  • 136,588
  • It's definitely a *very bad* idea to do \edef\array{...} in LaTeX. Do you notice the triple emphasis? ;-) – egreg Oct 21 '22 at 08:28
  • @egreg Unfortunately I don't understand your comment. In my answer \edef comes from the original code. I've never understood TeX expansions and things like that. Any suggestion to learn it? – Ignasi Oct 21 '22 at 08:36
  • Please, change \array to any undefined command and warn the OP that redefining \array is very likely to break their documents. – egreg Oct 21 '22 at 08:39
  • Don't use \def and \edef unless you really know what your are doing. Always use \newcommand so that you get warned if you overwrite an existing command. – Ulrike Fischer Oct 21 '22 at 08:44
  • @UlrikeFischer You're right! Thank you for reminding me. – Ignasi Oct 21 '22 at 08:53
  • Nitpick: This is not a TikZ array, it's a PGFmath array. There's no inbuilt function to change values of an array in the array[index] = new value way of doing things. – Qrrbrbirlbel Oct 21 '22 at 09:00