¿Hay alguna manera de almacenar información en algo así como una matriz?

¿Hay alguna manera de almacenar información en algo así como una matriz?

Me gustaría almacenar información básica sobre personas en un archivo y quiero que LaTeX pueda procesar esta información. Más específicamente, me gustaría almacenar algo como:

id:john1; fname: John; lname: Doe; mail: [email protected]
id:harry1; fname: Harry; lname: Potter; mail: [email protected]

etc. ¿Es esto posible en LaTeX, es decir, hay alguna manera de 1) hacer esta lista y 2) colocar esta información en un documento con algo como \data{john1}{fname}?

Respuesta1

Puede leer el archivo por \readprimitivo. Los datos se almacenan en secuencias de control \base:id:name. La \datamacro simplemente expande esta secuencia de control.

\newread\basein
\def\readbase #1 {\bgroup \endlinechar=-1 \openin\basein=#1 \readbaseA}
\def\readbaseA{\ifeof\basein \egroup \else
   \read\basein to\tmp
   \ifx\tmp\empty \else \expandafter\base\tmp; :.; \fi
   \expandafter\readbaseA \fi
}
\def\base id:#1; {\def\baseid{#1}\baseA}
\def\baseA #1:#2#3; {\ifx\end#1\end\else
   \expandafter\gdef\csname base:\baseid:#1\endcsname{#2#3}%
   \expandafter\baseA\fi
}
\def\data#1#2{\csname base:#1:#2\endcsname}

\readbase base.txt  % reading the file

\data{john1}{fname}

Respuesta2

Una implementación autónoma:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\storedata}{mm}
 {% pass control to an inner function
  \konewka_store_data:nn { #1 } { #2 }
 }

\DeclareExpandableDocumentCommand{\getdata}{mm}
 {% just retrieve the property from the appropriate property list
  \prop_item:cn { g_konewka_data_#1_prop } { #2 }
 }

\seq_new:N \l__konewka_data_temp_seq
\seq_new:N \l__konewka_field_temp_seq

\cs_new_protected:Nn \konewka_store_data:nn
 {
  % create a property list for an ID
  \prop_new:c { g_konewka_data_#1_prop }
  % split the second argument
  \seq_set_split:Nnn \l__konewka_data_temp_seq { ; } { #2 }
  % process each field
  \seq_map_inline:Nn \l__konewka_data_temp_seq
   {
    \__konewka_process_field:nn { #1 } { ##1 }
   }
 }

% we need a colon with the appropriate category code    
\group_begin:
\char_set_lccode:nn { `? } { `: }
\tl_to_lowercase:n
 {
  \group_end:
  \tl_const:Nn \c_konewka_colon_tl { ? }
 } 

% split the field at the colon and store the property    
\cs_new_protected:Nn \__konewka_process_field:nn
 {
  \seq_set_split:NVn \l__konewka_data_field_seq \c_konewka_colon_tl { #2 }
  \prop_gput:cxx { g_konewka_data_#1_prop }
   { \seq_item:Nn \l__konewka_data_field_seq { 1 } }
   { \seq_item:Nn \l__konewka_data_field_seq { 2 } }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }

\ExplSyntaxOff

\storedata{john1}{fname: John; lname: Doe; mail: [email protected]}
\storedata{harry1}{fname: Harry; lname: Potter; mail: [email protected]}

\begin{document}

\begin{tabular}{cccc}
Id & fname & lname & mail \\
\hline
\texttt{john1} & \getdata{john1}{fname} & \getdata{john1}{lname} & \getdata{john1}{mail} \\
\texttt{harry1} & \getdata{harry1}{fname} & \getdata{harry1}{lname} & \getdata{harry1}{mail} \\
\end{tabular}

\end{document}

ingrese la descripción de la imagen aquí


Una versión que también permite leer los datos de un archivo. Aquí el archivo se agrega con filecontents, pero puede ser cualquiera, siempre que el formato sea el que se muestra. Se ignorarán los espacios alrededor de dos puntos y punto y coma.

\begin{filecontents*}{\jobname.csv}
id:john1; fname: John; lname: Doe; mail: [email protected]
id:harry1; fname: Harry; lname: Potter; mail: [email protected]
\end{filecontents*}

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\storedata}{mm}
 {% pass control to an inner function
  \konewka_add_id:n { #1 }
  \konewka_store_data:nn { #1 } { #2 }
 }

\NewDocumentCommand{\readdata}{m}
 {
  \konewka_read_data:n { #1 }
 }

\DeclareExpandableDocumentCommand{\getdata}{mm}
 {% just retrieve the property from the appropriate property list
  \prop_item:cn { g_konewka_data_#1_prop } { #2 }
 }

\NewDocumentCommand{\listIDs}{}
 {% just an example
  \seq_use:Nn \g_konewka_id_seq { ,~ }
 }

%%% variables

% we need a colon with the appropriate category code    
\tl_const:Nx \c_konewka_colon_tl { \tl_to_str:n {:} }
% other variables
\seq_new:N \g_konewka_id_seq

\tl_new:N \l__konewka_id_tl
\seq_new:N \l__konewka_data_temp_seq
\seq_new:N \l__konewka_field_temp_seq
\ior_new:N \g__konewka_read_data_stream

%%% variants of kernel functions
\cs_generate_variant:Nn \seq_set_split:Nnn { NV , NVV }
\cs_generate_variant:Nn \prop_gput:Nnn { cxx }

%%% our functions

% add the new id to a sequence for possible later usage
\cs_new_protected:Nn \konewka_add_id:n
 {
  \seq_gput_right:Nn \g_konewka_id_seq { #1 }
 }
\cs_generate_variant:Nn \konewka_add_id:n { V }

% the inner function for \storedata
\cs_new_protected:Nn \konewka_store_data:nn
 {
  % create a property list for an ID
  \prop_new:c { g_konewka_data_#1_prop }
  % split the second argument at semicolons
  \seq_set_split:Nnn \l__konewka_data_temp_seq { ; } { #2 }
  % populate the property list
  \__konewka_process_entry:n { #1 }
 }

% the inner function for \readdata
\cs_new_protected:Nn \konewka_read_data:n
 {
  \ior_open:Nn \g__konewka_read_data_stream { #1 }
  \ior_map_inline:Nn \g__konewka_read_data_stream
   {
    % split a line into fields
    \seq_set_split:Nnn \l__konewka_data_temp_seq { ; } { ##1 }
    % retrieve the first field (ID)
    \seq_pop_left:NN \l__konewka_data_temp_seq \l__konewka_id_tl
    % split at colon and set the ID to the second part
    \seq_set_split:NVV \l__konewka_data_field_seq \c_konewka_colon_tl \l__konewka_id_tl
    \tl_set:Nx \l__konewka_id_tl { \seq_item:Nn \l__konewka_data_field_seq { 2 } }
    % add the id to the list
    \konewka_add_id:V \l__konewka_id_tl
    % populate the property list
    \__konewka_process_entry:V \l__konewka_id_tl
   }
 }

% auxiliary function
\cs_new_protected:Nn \__konewka_process_entry:n
 {
  \seq_map_inline:Nn \l__konewka_data_temp_seq
   {
    \seq_set_split:NVn \l__konewka_data_field_seq \c_konewka_colon_tl { ##1 }
    \prop_gput:cxx { g_konewka_data_#1_prop }
     { \seq_item:Nn \l__konewka_data_field_seq { 1 } }
     { \seq_item:Nn \l__konewka_data_field_seq { 2 } }
   }
 }
\cs_generate_variant:Nn \__konewka_process_entry:n { V }

\ExplSyntaxOff

\readdata{\jobname.csv}
\storedata{uthor1}{fname: Algernon; lname: Uthor; mail: [email protected]}
\storedata{riter1}{fname: Walter; lname: Riter; mail: [email protected]}

\begin{document}

\begin{tabular}{cccc}
Id & fname & lname & mail \\
\hline
\texttt{john1} & \getdata{john1}{fname} & \getdata{john1}{lname} & \getdata{john1}{mail} \\
\texttt{harry1} & \getdata{harry1}{fname} & \getdata{harry1}{lname} & \getdata{harry1}{mail} \\
\texttt{uthor1} & \getdata{uthor1}{fname} & \getdata{uthor1}{lname} & \getdata{uthor1}{mail} \\
\texttt{riter1} & \getdata{riter1}{fname} & \getdata{riter1}{lname} & \getdata{riter1}{mail} \\
\end{tabular}

\medskip

The IDs are: \listIDs

\end{document}

ingrese la descripción de la imagen aquí

información relacionada