3

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.

4

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).

enter image description here

\documentclass{article}

\usepackage{etoolbox}

\newcommand{\setfield}[3]{%
  \expandafter\def\csname #1@#2\endcsname{#3}%
  \listcsgadd{#1}{#2}%
}
\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. – Lasse Kliemann Feb 17 '18 at 10:04
  • @LasseKliemann: I've added some updates to the answer. It now provides and alias or a copy function. – Werner 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 :) – gigabytes Feb 18 '18 at 14:18
2
\documentclass[10pt]{article}
\usepackage{readarray}
\begin{document}
\readarraysepchar{ }
\def\mydata{alpha beta gamma delta}
\readarray\mydata\myarray[-,2]% Read \mydata as 2 fields into 2-D \myarray
Cell (2,2) has \myarray[2,2]
whereas cell (1,2) has \myarray[1,2]
\end{document}

enter image description here

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}
\usepackage{readarray,filecontents}
\begin{filecontents*}{mydatafile}
alpha, beta
gamma, delta force
\end{filecontents*}
\begin{document}
\readarraysepchar{,}
\readdef{mydatafile}{\mydata}
\readarray*\mydata\myarray[-,\ncols]% Read \mydata as 2 fields into 2-D \myarray
Cell (2,2) has \myarray[2,2]
whereas cell (1,2) has \myarray[1,2]
\end{document}

enter image description here

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}
\usepackage{readarray}
\makeatletter
\gdef\setfield#1[#2,#3]#4{%
  \expandafter\gdef\csname\expandafter\@gobble\string#1[#2,#3]\endcsname{#4}}%
\makeatother
\begin{document}
\readarraysepchar{ }
\def\mydata{alpha beta gamma delta}
\readarray\mydata\myarray[-,2]% Read \mydata as 2 fields into 2-D \myarray
Cell (2,2) has \myarray[2,2]
whereas cell (1,2) has \myarray[1,2]

\setfield\myarray[1,2]{$\beta$}
Cell (1,2) now has \myarray[1,2].
\end{document}

enter image description here

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.