# Record-like data structure?

I would need something like this:

\setfield{record1}{field1}{alpha}
\setfield{record1}{field2}{beta}
\setfield{record2}{field1}{gamma}
\setfield{record2}{field2}{delta}
\assign{record3}{record2}
\getfield{record1}{field1} % should expand to alpha
\getfield{record1}{field2} % should expand to beta
\getfield{record2}{field1} % should expand to gamma
\getfield{record2}{field2} % should expand to delta
\getfield{record3}{field1} % should expand to gamma
\getfield{record3}{field2} % should expand to delta


Is there a package for this? I could live without the assign command.

Essentially \setfield is a \def where the control sequence name is constructed using the first two arguments. \getfield merely sets the requested control sequence (no error checking is performed; \csname ... \endcsname returns \relax if the record/field does not exist).

\documentclass{article}

\usepackage{etoolbox}

\newcommand{\setfield}[3]{%
\expandafter\def\csname #1@#2\endcsname{#3}%
}
\newcommand{\getfield}[2]{%
\ifcsname #1@alias\endcsname
\expandafter\expandafter\expandafter\csname \csname #1@alias\endcsname @#2\endcsname
\else
\csname #1@#2\endcsname
\fi}
\newcommand{\recordalias}[2]{\expandafter\def\csname #2@alias\endcsname{#1}}
\newcommand{\recordcopy}[2]{%
\renewcommand*{\do}[1]{%
\expandafter\edef\csname #2@##1\endcsname{\csname #1@##1\endcsname}}%
\dolistcsloop{#1}%
}

\begin{document}

\setfield{record1}{field1}{alpha}
\setfield{record1}{field2}{$\beta$}
\setfield{record2}{field1}{gamma}
\setfield{record2}{field2}{$\delta$}

\recordalias{record2}{record3}
\recordcopy{record2}{record4}

\getfield{record1}{field1} % should expand to alpha
\getfield{record1}{field2} % should expand to $\beta$
\getfield{record2}{field1} % should expand to gamma
\getfield{record2}{field2} % should expand to $\delta$
\getfield{record3}{field1} % should expand to gamma
\getfield{record3}{field2} % should expand to $\delta$

\setfield{record2}{field1}{$\gamma$}

\getfield{record2}{field1} % should expand to $\gamma$
\getfield{record3}{field1} % should expand to $\gamma$
\getfield{record4}{field1} % should expand to gamma

\end{document}


Added are two types of assignments:

• alias via \recordalias{<first>}{<second>} - this makes the <second> record an alias for <first>;
• copy via \recordcopy{<first>}{<second>} - this sequentially copies all the fields from <first> into <second> using list processing provided by etoolbox.
• Thanks for all the answers. This one fits my needs best. Just curious: Could anyone think of a copy function for those records? May be difficult without having a list of possible field names. Feb 17 '18 at 10:04
• @LasseKliemann: I've added some updates to the answer. It now provides and alias or a copy function. Feb 18 '18 at 4:56
• I don't think you need the \expandafters in \getfield and only the first in \do appears necessary.
– TH.
Feb 18 '18 at 8:15
• It might be interesting to add that this is basically the underlying mechanism of key val systems like pgfkeys :) Feb 18 '18 at 14:18
\documentclass[10pt]{article}
\begin{document}
\def\mydata{alpha beta gamma delta}
Cell (2,2) has \myarray[2,2]
whereas cell (1,2) has \myarray[1,2]
\end{document}


If the data is in a file, also no problem. Note that \readdef, while reading the file, sets \ncols to the number of fields detected in the first row and can be used, instead of an explicit 2, for the \readarray. I also demonstrate the use of a different separator (comma instead of space) and show how the * option of \readarray will remove leading and trailing spaces.

\documentclass[10pt]{article}
\begin{filecontents*}{mydatafile}
alpha, beta
gamma, delta force
\end{filecontents*}
\begin{document}
Cell (2,2) has \myarray[2,2]
whereas cell (1,2) has \myarray[1,2]
\end{document}


FINALLY, if changing cell data on the fly is a requirement, I implement here the macro \setfield\<array name>[<row>,<column>]{<data>}:

\documentclass[10pt]{article}
\makeatletter
\gdef\setfield#1[#2,#3]#4{%
\expandafter\gdef\csname\expandafter\@gobble\string#1[#2,#3]\endcsname{#4}}%
\makeatother
\begin{document}
\setfield\myarray[1,2]{$\beta$}