
Para algunos #1
, #2
defino el \csname base:#1:#2\endcsname
. Entonces defino lo siguiente
\def\data#1#2{\ifcsname base:#1:#2\endcsname \csname base:#1:#2\endcsname\fi}
y después
\newcommand{\name}[1]{\data{#1}{fname} \data{#1}{lname}}
Puede verlo \data
como una matriz bidimensional con información sobre los usuarios con id #1
. Ahora quiero asegurarme de que la entrada original se imprima cuando no se encuentre la identificación de usuario. Es decir, asumo que tengo usuarios john
y elvis
con información completa. Luego \name{elvis}
se imprimirá como Elvis Presley
. Ahora quiero #1
imprimirlo si \csname base:#1:#2
no está definido, es decir, lo \name{santa}
imprimiré santa
ya que Santa no está en mi base de usuarios. Intenté trabajar con
\ifx\data{#1}{fname}\empty #1\else ...\fi
pero no pude hacerlo funcionar. ¿Cómo debería hacer esto?
Respuesta1
Sería más fácil ver lo que estás haciendo y la mejor manera de responder esto con un completoejemplo de trabajo mínimo (MWE), pero ignorando esto...
La solución más sencilla sería simplemente redefinir \data
como:
\def\data#1#2{%
\ifcsname base:#1:#2\endcsname \csname base:#1:#2\endcsname%
\else #1%
\fi}
pero sospecho que esto no es lo que quieres como lo \name{santa}
producirás ahora santa santa
. En cambio, creo que probablemente quieras definir algo como lo siguiente:
\newif\ifDataExists
\newcommand\CheckForData[1]{%
% assuming that fname a reasonable proxy to check for data?
\ifcsname base:#1:fname\endcsname\DataExiststrue
\else\DataExistsfalse
\fi%
}
\newcommand\name[1]{\CheckForData{#1}%
\ifDataExists{#1}{fname} \data{#1}{lname}\else #1\fi}
Ahora, usando su \data
comando original, \name{santa}
producirá un único archivo santa
.
Respuesta2
\documentclass{article}
\newcommand\data[2]{%
\ifcsname base:#1:#2\endcsname
\csname base:#1:#2\endcsname
\else
#1%
\fi
}
\newcommand{\name}[1]{\data{#1}{fname} \data{#1}{lname}}
% populate one of the databases (I don't know how you do it)
\expandafter\def\csname base:elvis:fname\endcsname{Elvis}
\expandafter\def\csname base:elvis:lname\endcsname{Presley}
\begin{document}
\name{elvis}
\name{santa}
\end{document}
Sería posible imprimir "santa" solo una vez, pero también complicaría la definición del \name
uso de controles de nivel inferior.
Si utilizó mi expl3
implementación propuesta, solo unas pocas modificaciones proporcionarían una \name
macro que tiene la propiedad que necesita:
\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}
{
\konewka_item:nn { #1 } { #2 }
}
\NewDocumentCommand{\listIDs}{}
{% just an example
\seq_use:Nn \g_konewka_id_seq { ,~ }
}
\NewDocumentCommand{\name}{m}
{
\konewka_if_key:nTF { #1 }
{
\konewka_item:nn { #1 } { fname }
\c_space_tl
\konewka_item:nn { #1 } { lname }
}
{
\texttt{#1}
}
}
%%% 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
% check if a key is present in the database
\prg_new_conditional:Nnn \konewka_if_key:n { p,T,F,TF }
{
\prop_if_exist:cTF { g_konewka_data_#1_prop }
{
\prg_return_true:
}
{
\prg_return_false:
}
}
% 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
}
}
% syntactic sugar
\cs_new:Npn \konewka_item:nn #1 #2
{% just retrieve the property from the appropriate property list
\prop_item:cn { g_konewka_data_#1_prop } { #2 }
}
% 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
\medskip
Print names: ``\name{john1}'' and ``\name{santa}''
\end{document}