
Для некоторых #1
я #2
определяю \csname base:#1:#2\endcsname
. Затем я определяю следующее
\def\data#1#2{\ifcsname base:#1:#2\endcsname \csname base:#1:#2\endcsname\fi}
и после этого
\newcommand{\name}[1]{\data{#1}{fname} \data{#1}{lname}}
Вы можете увидеть \data
как двумерный массив с информацией о пользователях с id #1
. Теперь я хочу убедиться, что исходный ввод печатается, когда идентификатор пользователя не найден. Т.е. предположим, что у меня есть пользователи john
и elvis
с полной информацией. Тогда \name{elvis}
будет печататься как Elvis Presley
. Теперь я хочу, чтобы #1
печаталось, если \csname base:#1:#2
не определено, т.е. \name{santa}
печатается, santa
так как Санта отсутствует в моей базе пользователей. Я пробовал работать с
\ifx\data{#1}{fname}\empty #1\else ...\fi
но не смог заставить его работать. Как мне это сделать?
решение1
Было бы легче увидеть, что вы делаете, и лучший способ ответить на этот вопрос — дать полный ответ.минимальный рабочий пример (MWE), но игнорируя это...
Самым простым решением было бы просто переопределить \data
это как:
\def\data#1#2{%
\ifcsname base:#1:#2\endcsname \csname base:#1:#2\endcsname%
\else #1%
\fi}
но я подозреваю, что это не то, что вы хотите, так как теперь \name{santa}
будет производить santa santa
. Вместо этого, я думаю, что вы, вероятно, хотите определить что-то вроде следующего:
\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}
Теперь, используя вашу исходную \data
команду, \name{santa}
создадим один файл santa
.
решение2
\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}
Напечатать слово «Санта» всего один раз было бы возможно, но это также усложнило бы определение \name
использования проверок более низкого уровня.
Если бы вы использовали предложенную мной expl3
реализацию, всего несколько изменений дали бы \name
макрос, обладающий необходимым вам свойством:
\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}