如何打破宏/如何实现开关或数组结构

如何打破宏/如何实现开关或数组结构

我正在寻找一种实现具有switch/case控制结构(或array解决方案)的宏的方法,因为它存在于每种编程语言中。

梅威瑟:

\documentclass[ngerman,12pt]{article}
\usepackage{etoolbox}

\newcommand*\foo[1]{%
    \ifstrequal{#1}{givemea}{box}{}%
    \ifstrequal{#1}{drawmea}{circle}{}%
    \ifstrequal{#1}{applesidontlikeare}{green}{}%
    \ifstrequal{#1}{life}{is full of surprises}{}%
}
\begin{document}
\foo{life}
\end{document}

你可以想象,如果我有 500 个条目,这个过程会非常慢,因为它与每一个价值在宏中。\break\return命令非常有用,因此如果找到该值,宏将中止。另外:我的字符串也将包含数字(在每个位置)。

或者有没有什么软件包可以用于这项工作?

(由于会有很多条目,我考虑将一个宏分成多个:\fooa,,\foob...所以,如果我调用\foo{life}它,会检查第一个字母l,然后调用\fool{life}。这也会加快这个过程。)

答案1

您不需要进行一系列线性的字符串相等性测试,而需要进行哈希查找:

\documentclass[12pt]{article}


\newcommand*\foo[1]{\csname FOO-#1\endcsname}
\newcommand*\setfoo[1]{\expandafter\def\csname FOO-#1\endcsname}

\setfoo{give1mea}{box}
\setfoo{draw2mea}{circle}
\setfoo{applesidontlikeare!!}{green}
\setfoo{life}{is full of surprises}
\setfoo{apple4dinner}{see?}


\begin{document}
\foo{life} \foo{apple4dinner}
\end{document}

答案2

expl3LaTeX3 的编程层提供了相关\str_case:nnF功能:这些仅比较“所需的范围”:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \strcases \str_case:nnF
\ExplSyntaxOff
\newcommand*\foo[1]{%
  \strcases{#1}%
    {%
      {givemea}           {box}
      {drawmea}           {circle}
      {applesidontlikeare}{green}
      {life}              {is full of surprises}
    }%
    {No match found!}%
}
\begin{document}
\foo{life}
\end{document}

请注意,对于非常长的列表,仍然必须对每个项目进行比较,直到找到匹配项,当项目接近末尾时,对于非常长的列表,比较速度会变慢。

另一种方法,类似于大卫的在使用查找表的意义上,就是使用prop

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\prop_new:N \l_my_prop
\prop_put:Nnn \l_my_prop {givemea}           {box}
\prop_put:Nnn \l_my_prop {drawmea}           {circle}
\prop_put:Nnn \l_my_prop {applesidontlikeare}{green}
\prop_put:Nnn \l_my_prop {life}              {is~full~of~surprises}
\newcommand* \foo [1]
  {
    \prop_get:NnNTF \l_my_prop {#1} \l_tmpa_tl
      { \tl_use:N \l_tmpa_tl }
      { No~match~found! }
}
\ExplSyntaxOff
\begin{document}
\foo{life}
\end{document}

此处的数据结构(目前)仅使用一个名称,但这意味着随着大小的增加,添加会相对较慢。但是,查找应该不会受到如此严重的影响(它使用分隔宏),尽管随着表大小的增加,查找也会下降。(对于“大”数据集,TeX 的哈希表可能是创建查找系统的最佳方式,如 David 的回答中所述。请参阅如何在 TeX 中实现(低级)数组了解更多。

答案3

以下示例比较字符串,直到找到匹配项。然后\@car获取第一个参数并抛出其余部分直到下一个参数\@nil,以便跳过以下比较:

\documentclass[12pt]{article}
\usepackage{etoolbox}

\makeatletter
\newcommand*\foo[1]{%
  \def\foo@##1##2{%
    \ifstrequal{#1}{##1}{\@car{##2}}{}%
  }%
  \foo@{givemea}{box}%
  \foo@{drawmea}{circle}%
  \foo@{applesidontlikeare}{green}%
  \foo@{life}{is full of surprises}%
  \@nil
}
\makeatother
\begin{document}
\foo{givemea} \foo{life}
\end{document}

结果

相关内容