Gibt es eine Möglichkeit, Informationen in so etwas wie einem Array zu speichern?

Gibt es eine Möglichkeit, Informationen in so etwas wie einem Array zu speichern?

Ich möchte einige grundlegende Informationen über Personen in einer Datei speichern und möchte, dass LaTeX diese Informationen verarbeiten kann. Genauer gesagt möchte ich etwas wie Folgendes speichern:

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

usw. Ist dies in LaTeX möglich, d. h. gibt es eine Möglichkeit, 1) diese Liste zu erstellen und 2) diese Informationen in einem Dokument zu platzieren, beispielsweise mit \data{john1}{fname}?

Antwort1

Sie können die Datei mit Primitiven lesen \read. Die Daten sind in Steuersequenzen gespeichert \base:id:name. Das \dataMakro expandiert einfach diese Steuersequenz.

\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}

Antwort2

Eine in sich geschlossene Implementierung:

\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}

Bildbeschreibung hier eingeben


Eine Version, die auch das Lesen der Daten aus einer Datei ermöglicht. Hier wird die Datei mit hinzugefügt filecontents, kann aber jede beliebige sein, solange das Format wie gezeigt ist. Leerzeichen um Doppelpunkte und Semikolons werden ignoriert.

\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}

Bildbeschreibung hier eingeben

verwandte Informationen