Adendo I

Adendo I

Eu tenho uma lista de key=valuestrings separadas por vírgula. Quero extrair o valor com base na chave. Algo um pouco parecido

\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

A intenção é que isso resultasse na string baz.

Como posso fazer isso?

Responder1

Você pode definir um analisador de valor-chave personalizado (assumindo que o conjunto de chaves deve ser variável):

\documentclass{article}

\makeatletter
\def\LookUpValue#1#2#3{%
  \@tempswafalse
  \gdef\LookUpValue@false{#3}%
  \xdef\@tempa{#1}%
  \LookUpValue@#2,\@end,}
\def\LookUpValue@#1,{%
  \ifx#1\@end
    \if@tempswa\@tempc\else\LookUpValue@false\fi
  \else
    \LookUpValue@@#1\@nil\expandafter\LookUpValue@\fi}
\def\LookUpValue@@#1=#2\@nil{%
  \edef\@tempb{#1}%
  \ifx\@tempa\@tempb\gdef\@tempc{#2}\@tempswatrue\fi
}
\makeatother

\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\textit{\LookUpValue{d}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}}

\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}

saída

Adendo I

Se você der uma olhada na resposta do @egreg, existe um recurso muito interessante que permite armazenar o resultado \LookUpValueem uma macro sem imprimi-lo. Aqui está uma maneira de conseguir isso no LaTeX2e (dada a minha solução principal):

\documentclass{article}

\makeatletter
\def\LookUpValue{\kernel@ifnextchar[\@LookUpValue{\@LookUpValue[\@tempa]}}
\def\@LookUpValue[#1]#2#3{%
  \@tempswafalse
  \begingroup
    \escapechar\m@ne
    \xdef\luv@namespace{\string#1}%
  \endgroup
  \xdef\reserved@a{#2}%
  \expandafter\LookUpValue@#3,\@end,}
\def\LookUpValue@#1,{%
  \ifx#1\@end
    \if@tempswa\@nameuse{@tempa}\let\@tempa\relax
      \expandafter\expandafter\expandafter\@gobble\fi%
  \else
    \LookUpValue@@#1\@nil\expandafter\LookUpValue@\fi}
\def\LookUpValue@@#1=#2\@nil{%
  \edef\reserved@b{#1}%
  \ifx\reserved@a\reserved@b\@namedef{\luv@namespace}{#2}\@tempswatrue\fi
}
\makeatother

\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\def\mypreset{a=foo,b=bar,c=baz,d=zyyzx}
\LookUpValue[\myval]{d}{\mypreset}{}

\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\textsc{\myval}
\end{document}

Adendo II

No entanto, se o conjunto de chaves cujos valores você tenta extrair estiver fixo em todo o documento, existe uma maneira mais simples:

\documentclass{article}
\usepackage{keyval}

\makeatletter
\newcommand\newspraffkey[1]{\define@key{spraffkeys}{#1}{\@namedef{value_of_#1}{##1}}}
\newcommand\LookUpValue[2]{%
  \begingroup
  \setkeys{spraffkeys}{#2}%
  \@nameuse{value_of_#1}%
  \expandafter\ifx\csname value_of_#1\endcsname\relax\else\expandafter\@gobbleaftergroup\fi
  \endgroup
}
\def\@gobbleaftergroup{\aftergroup\@gobble}
\makeatother

\newspraffkey{a}
\newspraffkey{b}
\newspraffkey{c}
\newspraffkey{d}

\begin{document}
\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\LookUpValue{d}{a=foo,b=bar,c=baz}{error:notfound}

\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}

Responder2

Uma versão com preenchimento de uma propertylista usando expl3sintaxe e procura pelo par de valores-chave relevante. Talvez não seja o caminho mais rápido, mas é bastante fácil de usar.

\documentclass{article}

\usepackage{xparse}


\ExplSyntaxOn
\cs_generate_variant:Nn \prop_put:Nnn {Nxn,Nxx}
\NewDocumentCommand{\LookUpValue}{mmm}{%
  \seq_set_from_clist:Nn \l_tmpa_seq {#2}
  \seq_map_inline:Nn \l_tmpa_seq {% Mapping through the sequence
    \seq_set_split:Nnn \l_tmpb_seq {=} {##1} 
    % Filling the property list
    \prop_put:Nxx \l_tmpa_prop {\seq_item:Nn \l_tmpb_seq {1}} {\seq_item:Nn \l_tmpb_seq {2}}
  }
  % Look if #1 is in the property list and display the value, otherwise #3
  \prop_if_in:NnTF \l_tmpa_prop {#1} {\prop_item:Nn \l_tmpa_prop {#1}} {#3}
}
\ExplSyntaxOff


\begin{document}

\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\LookUpValue{foobar}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}
\end{document}

insira a descrição da imagem aqui

Responder3

O código a seguir usa as funções de valor-chave em expl3; aqui eu exploro “chaves desconhecidas”, algo melhor pode ser feito se as chaves forem conhecidas antecipadamente.

Se um argumento opcional for fornecido, deverá ser uma sequência de controle que será (re)definida para o resultado.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\LookUpValue}{ommm}
 {
  \str_set:Nn \l_spraff_given_key_str { #2 }
  \tl_clear:N \l_spraff_output_tl
  \keys_set:nn { spraff/random } { #3 }
  \tl_if_empty:NT \l_spraff_output_tl
   {
    \tl_set:Nn \l_spraff_output_tl { #4 }
   }
  \IfNoValueTF{#1}
   { \tl_use:N \l_spraff_output_tl }
   { \tl_set_eq:NN #1 \l_spraff_output_tl }
 }

\keys_define:nn { spraff/random }
 {
  unknown .code:n =
   \str_if_eq:NNT \l_spraff_given_key_str \l_keys_key_tl
    {
     \tl_set:Nn \l_spraff_output_tl { #1 }
    }
 }
\ExplSyntaxOff

\begin{document}

\LookUpValue{c}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\LookUpValue{e}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\LookUpValue[\temp]{a}{a=foo,b=bar,c=baz,d=zyyzx}{error:notfound}

\texttt{\meaning\temp}

\end{document}

insira a descrição da imagem aqui

informação relacionada