有没有办法编写一个用户定义的 Latex 命令,该命令不采用任何参数并从字符串存储库中返回第 n 个字符串?
baseball,marble,coin,watermelon,beachball
约翰尼向乔扔了一个\myWord{1}
、、\myWord{3}
和一个\myWord{4}
。
我的目标是获得这样的回报:
Johnny threw a baseball, coin, and a watermelon to Joe.
(或许会随意插入一个词来表示不带任何争论,就像 一样\myWord{}
)。
答案1
expl3
在(加载者)的帮助下xparse
:
\documentclass[]{article}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_ignoramus_words_seq
\int_new:N \l_ignoramus_count_int
\NewDocumentCommand \setwordlist { m }
{
\seq_set_from_clist:Nn \l_ignoramus_words_seq { #1 }
\int_set:Nn \l_ignoramus_count_int { \seq_count:N \l_ignoramus_words_seq }
}
\NewDocumentCommand \myword { o }
{
\seq_item:Nn \l_ignoramus_words_seq
{
\IfNoValueTF { #1 }
{ \int_rand:n { \l_ignoramus_count_int } }
{ #1 }
}
}
\ExplSyntaxOff
\setwordlist{baseball,marble,coin,watermelon,beachball}
\begin{document}
Johnny threw a \myword, \myword, and a \myword\ to Joe.
Johnny threw a \myword[1], \myword[3], and a \myword[4] to Joe.
\end{document}
答案2
您可以使用etoolbox
处理列表:
\documentclass{article}
\usepackage{etoolbox,xfp}
\newcounter{wordcnt}
\newcommand{\setwordlist}[1]{%
\setcounter{wordcnt}{0}% Reset word counter
\renewcommand{\do}[1]{% With every element in word list, ...
\stepcounter{wordcnt}% ... step word counter ...
\expandafter\def\csname wordlist\thewordcnt\endcsname{##1}% ... and store word.
}%
\docsvlist{#1}% Process word list
}
\newcommand{\myWord}[1]{%
% https://tex.stackexchange.com/q/53068/5764
\if\relax\detokenize{#1}\relax
\csname wordlist\fpeval{randint(1,\value{wordcnt})}\endcsname
\else
\csname wordlist#1\endcsname
\fi
}
\begin{document}
\setwordlist{baseball,marble,coin,watermelon,beachball}
Johnny threw a \myWord{1}, \myWord{3}, and a \myWord{4} to Joe.
Johnny threw a \myWord{1}, \myWord{}, and a \myWord{4} to Joe.
\end{document}
请注意,随机选择使用xfp
并且不考虑任何形式的无放回选择。因此,可能会抽取重复项。