我想使用宏来xstring
对由 a 生成的字符串进行操作\ref{}
。
具体来说,我有一个宏,它“填充”十进制数,以便按字典顺序排序;换句话说,12.9 应该变成 00012.00009。\padref{}
下面的宏就是这么做的。
但问题是我想让它对 进行操作\ref{}
,但这不起作用:字符串以某种方式被区别对待。 \StrCut
无法看到它包含一个点,但\StrLen
能够看到它有多长。
我怀疑这与扩张有关,但我最初的尝试\edef
没有成功。
如果它很重要,那么潜在的动机是我有一堆对列表项的引用(如下所示\ref{one}
),我想将其用作\padref{}
索引键。
\documentclass{amsart}
\usepackage{enumitem}
\usepackage{ifthen,calc}
\usepackage{xstring}
\parskip3ex
% takes a reference like 2.9 or 10.1 and pads it to five digits, so 00002.00009 and 00010.00001
% lexicographical sorting on this will ``do the right thing''
\newcommand\padref[1]{%
\StrCut{#1}{.}\chap\ques%
\StrLen{\chap}[\chaplen]%
\StrLen{\ques}[\queslen]%
\StrGobbleRight{00000}{\chaplen}%
\chap%
.%
\StrGobbleRight{00000}{\queslen}%
\ques%
}
\begin{document}
% this works, gives 00012.00009
Pad 12.9: \padref{12.9}
% this gives 001.1.00000
% the string is somehow not recognized (it "doesn't" contain a dot)
% but is also recognized (note that three characters were dropped from the first 00000)
Pad 1.1 given as a reference: \padref{\ref{one}}
% the following confuses me
\ref{one}
1.1
\ifthenelse{\equal{\ref{one}}{1.1}}{are the same}{are different}
This is just a silly list so I can have a reference.
\begin{enumerate}[label=\arabic*,ref=\arabic*.]
\item
\begin{enumerate}[label=\arabic*,ref=\theenumi\arabic*]
\item hi\label{one}
\item there
\end{enumerate}
\end{enumerate}
\end{document}
答案1
我们可以使用\getrefnumber
fromrefcount
并且避免enumitem
添加括号的习惯。
\documentclass{amsart}
\usepackage{enumitem}
\usepackage{refcount}
\usepackage{xparse}
\ExplSyntaxOn
% user interface
\NewDocumentCommand{\padref}{m}
{
\newman_padref_main:n { #1 }
}
% variables and constants
\int_const:Nn \c_newman_padref_padding_int { 5 } % change here
\tl_new:N \l__newman_padref_ref_tl
\seq_new:N \l__newman_padref_parts_seq
\seq_new:N \l__newman_padref_parts_out_seq
% utilities
\cs_set_eq:NN \newman_padref_getrefnumber:n \getrefnumber
% internal code
\cs_new_protected:Nn \newman_padref_main:n
{
% save the expanded reference
\tl_set:Nx \l__newman_padref_ref_tl
{
\newman_padref_getrefnumber:n { #1 }
}
% with enumitem we get unwanted braces; remove them recursively
\__newman_padref_removebraces:N \l__newman_padref_ref_tl
% split at periods
\seq_set_split:NnV \l__newman_padref_parts_seq { . } \l__newman_padref_ref_tl
% pad each part and output it with a period in between
\seq_set_map:NNn
\l__newman_padref_parts_out_seq
\l__newman_padref_parts_seq
{ \__newman_padref_pad:n { ##1 } }
\seq_use:Nn \l__newman_padref_parts_out_seq { . }
}
\cs_new:Nn \__newman_padref_pad:n
{% count the number of characters and pad up to the desired number
\prg_replicate:nn { \c_newman_padref_padding_int - \tl_count:n { #1 } } { 0 } #1
}
\cs_new:Nn \__newman_padref_removebraces:N
{
\int_compare:nT
{
\tl_count:N #1 < \tl_count_tokens:V #1 % there are braces
}
{
\tl_set:Nx #1 { \tl_map_function:NN #1 \use:n } % remove braces
\__newman_padref_removebraces:N #1 % restart the recursion
}
}
\cs_generate_variant:Nn \tl_count_tokens:n { V }
\ExplSyntaxOff
\begin{document}
Pad \ref{one} given as a reference: \padref{one}
This is just a silly list so I can have a reference.
\begin{enumerate}[label=\arabic*,ref=\arabic*.]
\item
\begin{enumerate}[label=\arabic*,ref=\theenumi\arabic*]
\item hi\label{one}
\item there
\end{enumerate}
\end{enumerate}
\end{document}