我经常需要做这样的事情:
IF x < 1, DO a
ELSE IF x < 2, DO b
ELSE IF x < 3, DO c
ELSE, DO d
使用etoolbox
,我最终嵌套了很多ifnumless
,如下所示:
\ifnumless{x}{1}{a}{
\ifnumless{x}{2}{b}{
\ifnumless{x}{3}{c}{
d
}
}
}
有没有更简单的方法来实现这一点?
答案1
一种“switchcase”可以很容易地编程:
\documentclass{article}
\makeatletter
\def\ifnumcase#1{%
\edef\elseif@{\string\elseif}\edef\endif@{\string\endif}%
\def\number@test{#1pt}\ifnumcase@i}
\def\ifnumcase@i#1{%
\def\ifnumcase@ii##1{%
\csname
@\ifdim\number@test#1pt first\else second\fi oftwo%
\endcsname{##1\gobto@endif}\ifnumcase@i}%
\edef\valeur@{\string#1}%
\csname
\ifx\valeur@\elseif@ idto@endif%
\else\ifx\valeur@\endif@ relax\else ifnumcase@ii\fi
\fi
\endcsname}
\def\idto@endif#1\endif{#1}
\def\gobto@endif#1\endif{}
\makeatother
\begin{document}
\ifnumcase{7.5}% <- number to test
{<1}{less than 1}
{<3}{less than 3}
{>5}{greater than 5}
% add other tests if needed
\elseif
between 3 and 5% all tests faild
\endif
\ifnumcase{3.14}% <- number to test
{<2}{less than 1}
{<3}{less than 3}
{<4}{less than 4}
{<10}{less than 10}
% add possible other tests
\endif
\end{document}
编辑:使用=
、、或测试的更完整和可扩展的解决方案:<
>
<=
<=
\documentclass{article}
\usepackage[T1]{fontenc}
\makeatletter
\def\elseif{\elseif}\def\endif{\endif}
\def\ifnumcase#1#2{%
\expandafter\ifx\expandafter\elseif\@car#2\@nil\expandafter\@firstoftwo
\else
\expandafter\ifx\expandafter\endif\@car#2\@nil\expandafter\expandafter\expandafter\@gobbletwo
\else\expandafter\expandafter\expandafter\@secondoftwo
\fi
\fi
\idto@endif
{\if@eqin#2=\@nil{\if@dimwitheq{#1}#2\@nil}{\ifdim#1pt#2pt }
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi\exec@arg{\ifnumcase@i{#1}}%
}%
}
\def\ifnumcase@i#1#2{\ifnumcase{#1}}
\def\if@eqin#1=#2\@nil{%
\ifx\@empty#2\@empty\expandafter\@secondoftwo
\else
\ifx\@empty#1\@empty\expandafter\expandafter\expandafter\@secondoftwo
\else\expandafter\expandafter\expandafter\@firstoftwo
\fi
\fi}
\def\if@dimwitheq#1#2=#3\@nil{\unless\ifdim#1pt\if<#2>\else<\fi#3pt }
\def\exec@arg#1#2\endif{#1}
\def\idto@endif#1\endif{#1}
\def\gobto@endif#1\endif{}
\makeatother
\begin{document}
\ifnumcase{3}
{<=1}{lt or equal 1}
{>=3}{gt or equal 3}
\elseif
beteween 1 and 3
\endif
\ifnumcase{4}% <- number to test
{<=1}{less or equal 1}
{<=3}{less or equal 3}
{=4}{equal 4}
{>=5}{greater or equal 5}
% add other tests if needed
\elseif
between 3 and 5% all tests faild
\endif
\edef\foo{\ifnumcase{5}% <- number to test
{<=1}{less or equal 1}
{<=3}{less or equal 3}
{=4}{equal 4}
{>=5}{greater or equal 5}
% add other tests if needed
\elseif
between 3 and 5% all tests faild
\endif}\meaning\foo
\ifnumcase{3.14}% <- number to test
{<2}{less than 1}
{<3}{less than 3}
{<4}{less than 4}
{<10}{less than 10}
% add possible other tests
\endif
\end{document}
答案2
根据还有谁需要使用代码,lualatex 是否可以工作?
\documentclass{article}
\begin{document}
\directlua{
x=1.5
}
\directlua{
if x<1 then
tex.print('a')
elseif x<2 then
tex.print('b')
elseif x<3 then
tex.print('c')
else
tex.print('d')
end
}
\end{document}
答案3
如果仅将其与整数进行比较,那么很容易:
\documentclass{minimal}
\def\getInteger#1{\expandafter\stripDecimals#1..!!}
\def\stripDecimals#1.#2.#3!!{\ifx\relax#1\relax0\else#1\fi}
\def\x{\getInteger{0.5}}
\begin{document}
\ifcase\x % 0
lt 1\or % 1
lt 2\or % 2
lt 3 % 3
\else gt 3 % else
\fi
\end{document}
答案4
一个可扩展且更完整的“切换”解决方案是:
\documentclass{article}
\makeatletter
\def\identoendif#1\endif{#1}
\def\oneoftoendif#1#2\endif{#1}
\def\gobbletoendif#1\endif{}
\newcommand*\ifstrsame[2]{%
\@nameuse{@\ifnum\pdfstrcmp{\detokenize{#1}}%
{\detokenize{#2}}=0first\else second\fi oftwo}%
}
\def\dimexpr@i#1{#1\dimexpr}
\def\ifnumcase#1{%
\ifstrsame{#1}\elseif\gobbletoendif{%
\ifstrsame{#1}\endif\@gobble\ifnumcase@i
}{#1}%
}
\def\ifnumcase@i#1#2{%
\ifstrsame{#2}\elseif\identoendif{%
\ifstrsame{#2}\endif{}{%
\ifdim\dimexpr#1pt\relax\dimexpr@i#2pt\relax
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\oneoftoendif}{\ifnumcase@ii{#1}}%
}%
}%
}
\def\ifnumcase@ii#1#2#3{\ifnumcase@i{#1}{#3}}
\makeatother
%% Examples:
\edef\x{%
\ifnumcase{6}% <- number to test
{<1}{less than 1}
{<3}{less than 3}
{>5}{greater than 5}
% add other tests if needed
\elseif
between 3 and 5% all tests failed
\endif
}
\show\x -> greater than 5
\edef\x{%
\ifnumcase{3.14}% <- number to test
{<2}{less than 1}
{<3}{less than 3}
{<4}{less than 4}
{<10}{less than 10}
% add possible other tests
\endif
}
\show\x -> less than 4
\edef\x{%
\ifnumcase{314}% <- number to test
{<2}{less than 1}
{<3}{less than 3}
{<4}{less than 4}
{<10}{less than 10}
% add possible other tests
\endif
}
\show\x -> empty
\begin{document}
% Nothing to do:
\ifnumcase\elseif\endif
\ifnumcase{3}\elseif\endif
\ifnumcase\endif
\ifnumcase{3}\endif
\end{document}
unbonpetit 的最新解决方案失败了
\ifnumcasse{3}
{=<1}{lt or equal 1}
{=>3}{gt or equal 3}
\elseif
beteween 1 and 3
\endif
和
\def\gobto@endif#1\endif{}
是多余的。
更通用的解决方案是
\makeatletter
\def\elseif{\@gobble\elseif}
\def\endif{\@gobble\endif}
\def\swap#1#2{#2#1}
\def\ifstrsame#1#2{%
\ifnum\pdfstrcmp{\detokenize{#1}}{\detokenize{#2}}=\z@
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}
\def\ifstrnull#1{%
\ifnum\pdfstrcmp{\detokenize{#1}}{}=\z@
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}
\def\ifcmdeq#1#2{%
\ifx#1#2\endif\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}
\def\if@eqin#1=#2\@nil{%
\ifstrnull{#2}\@secondoftwo{\ifstrnull{#1}\@secondoftwo\@firstoftwo}%
}
\def\if@dimwitheq#1#2=#3\@nil{\unless\ifdim#1pt\if<#2>\else<\fi#3pt }
\def\docasecallback#1#2\endif{#1}
\def\doelsepart#1\endif{#1}
\def\ifnumcase#1#2{%
\expandafter\ifcmdeq\@car#2\@nil\elseif\@firstoftwo{%
\expandafter\ifcmdeq\@car#2\@nil\endif\@gobbletwo\@secondoftwo
}%
\doelsepart{%
\expandafter\expandafter\expandafter
\if@eqin\checkcomparators#2\@nil=\@nil{%
\expandafter\expandafter\expandafter\swap
\expandafter\expandafter\expandafter
{\checkcomparators#2\@nil}{\if@dimwitheq{#1}}\@nil
}{%
\ifdim#1pt#2pt %
}
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
\docasecallback{\ifnumcase@i{#1}}%
}%
}
\def\ifnumcase@i#1#2{\ifnumcase{#1}}
\def\checkcomparators#1#2#3\@nil{%
\romannumeral
\ifstrsame{#1}={\ifstrsame{#2}<{0<=#3}{\ifstrsame{#2}>{0>=#3}{0 #1#2#3}}%
}{0 #1#2#3}%
}
\makeatother