(这是我在这里的第一个问题,对于它的任何“副作用”深表歉意......)
我想实现的是,根据 的值\MyR
(0 到 1 之间的数字,不包括 1)选择集合中的第一个/第二个/...项。在下面的 MWE 中,集合以 格式实现{item1\or item2\or item3 ...}
。例如,如果集合有两个元素:那么,对于低于 0.5{item1\or item2}
的值,将返回 ,对于高于 0.5 的值,将返回 。对于集合,0.33 将产生 ,而 0.34 将导致。下面我使用,并计算应返回其哪个分支。\MyR
item1
item2
{item1\or item2\or item3}
item1
item2
\ifcase
版本(*)
(见下文,通过 实现)似乎有效。但是,当我们取消注释最后一行(但只有一行) 时,\newcommandFromSet
变体(**)
和(***)
( 的两次尝试)会失败。 的成功似乎证明了基本概念的合理性,但我如何才能纠正 的定义?谢谢!\FromSet
%\fpeval...
(*)
\FromSet
(关联给@egreg's \CountToken
。)
[格式{item1\SomeShortToken item2\SomeShortToken item3 ...}
要容易输入,计算项目数也是为了方便用户。]
\documentclass{article} %% MWE
\usepackage{xfp}
\def\finish{\finish} %% Frequency of token #1 (stored
\def\CountToken[#1,#2]{% %% in counter #2) in what's
\def\TestedToken{#1}% %% between \CountToken[#1,#2]
\ifdefined#2#2=0 \else\newcount#2\fi %% and \finish. Code copied from
\let\TotalOccurrence#2% %% https://tex.stackexchange.com
\let\next\TestNext\next %% questions/525556/token-
} %% counter-strange-behaviour-
\long\def\TestNext#1{% %% of-math-mode (egreg's version)
\def\CurrentToken{#1}% %%
\ifx\CurrentToken\finish %%
\let\next\relax %%
\else %%
\ifx\CurrentToken\TestedToken %%
\advance\TotalOccurrence by 1 %%
\fi %%
\fi %%
\next %%
} %%
\newcommand{\MyR}{0.67} %% my "global variable".
\newcommand{\newcommandFromSet}[2]{\CountToken[\or,\cnti]#2\finish %% (*)
\xdef#1{\ifcase\fpeval{floor(\MyR*(1+\cnti))} #2\fi}}
\newcommand{\FromSet}[1]{\CountToken[\or,\cnti]#1\finish %% (**)
\ifcase\fpeval{floor(\MyR*(1+\cnti))} #1\fi}
%\renewcommand{\FromSet}[1]{\newcommandFromSet{\MyTemp}{#1}\MyTemp} %% (***)
\begin{document}
\newcommandFromSet{\MyText}{first\or second\or third}
\newcommandFromSet{\MyNumber}{11\or 12\or 13}
The \MyText\ number is \MyNumber, I repeat,
\fpeval{1*\MyNumber}. %% everything seems to be good.
The \FromSet{first\or second\or third} number is %% this line seems to work.
\FromSet{11\or 12\or 13}, I repeat, %% this line also seems to work.
%\fpeval{1*\FromSet{\or 11\or 12\or 13}}. %% ! Extra \or. \TestedToken ->\or
\end{document}
答案1
\or
恐怕你不能在那种情况下使用。但代码可以变得更简单。
我更喜欢用逗号分隔项目,而不是用 分隔\or
,这样\FromSet
宏是完全可扩展的。
通过\clist_count:n
可扩展地访问项目的数量,我们可以缩放变量;然后截断并加 1。
\documentclass{article}
\usepackage{xfp}
\ExplSyntaxOn
\NewDocumentCommand{\newcommandFromSet}{O{\MyR}mm}
{
\cs_new:Npx #2
{
\clist_item:nn { #3 }
{
\fp_eval:n { trunc(#1*\clist_count:n { #3 },0) + 1 }
}
}
}
\NewExpandableDocumentCommand{\FromSet}{O{\MyR}m}
{
\clist_item:nn { #2 }
{
\fp_eval:n { trunc(#1*\clist_count:n { #2 },0) + 1 } }
}
\ExplSyntaxOff
\newcommand{\MyR}{0.67} %% my "global variable".
\newcommand{\MyS}{0.1} %% another "global variable".
\begin{document}
\newcommandFromSet{\MyText}{first,second,third}
\newcommandFromSet{\MyNumber}{,11,12,13}
The \MyText\ number is \MyNumber, I repeat,
\fpeval{1*\MyNumber}.
The \FromSet{first,second,third} number is
\FromSet{11,12,13}, I repeat,
\fpeval{1*\FromSet{11,12,13}}.
\newcommandFromSet[\MyS]{\MyTextA}{first,second,third}
\newcommandFromSet[\MyS]{\MyNumberA}{11,12,13}
The \MyTextA\ number is \MyNumberA, I repeat,
\fpeval{1*\MyNumberA}.
The \FromSet[\MyS]{first,second,third} number is
\FromSet[\MyS]{11,12,13}, I repeat,
\fpeval{1*\FromSet[\MyS]{11,12,13}}.
\end{document}
请注意,您可以使用不同的变量;默认值为\MyR
。