对更新后问题的回复

对更新后问题的回复

我想动态定义一些宏,这些宏本质上是创建一个\refs 列表。我似乎能够定义这些宏,但无法打印它们。

这是我的 M(non)WE:

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\edef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{#1: \csname DP@#1\endcsname}
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

我希望\Assigned{}宏打印出“分配”给该人的项目编号。也就是说,在itemise上述环境之后,我应该得到:

fred: 1,3
julie: 2,4,5

不幸的是,我缺少产品编号,我只得到:

fred:
julie:

M(non)WE latex 没有任何问题,但出于我不明白的原因,\Assigned宏没有扩展。我尝试过使用\expandafter1 次或多次的多种变体,\edef……但似乎没有任何效果。

在日志文件中,\typeout{}上面的调用产生了:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: `\DP@fred`
ASSIGNED: `\DP@julie`

因此看起来, 的\DP@#1创建是正确的,而宏\Assigned{}不起作用,这可能是一个扩展问题。使用\edef不起作用……但扩展问题发生在 内部,这一事实表明\typeout我做了一些更根本的错误。

谁能告诉我如何解决这个问题?

我的下一个愿望是让它打印“1,3-6,8”,而不是“1,3,4,5,6,8”。但首先要做的是!

答案1

环境enumerate添加了一个组,因此对的更改\DP@#1是本地的,在环境关闭后会丢失。因此,该示例使定义成为全局的:

\documentclass{article}

\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname
    \edef\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}%
  \else
    \edef\DP@tmp{\@currentlabel}%
  \fi
  \global\expandafter\let\csname DP@#1\endcsname\DP@tmp
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  % \expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
  \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}  
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3  
\Assigned{julie}  % should print 2,4,5

\end{document}

结果:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5

范围压缩更新

该示例解析逗号列表\DP@#1并定义\Assign#1连续条目的压缩范围:

\documentclass{article}

\usepackage{kvoptions}

\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname
    \edef\DPx@tmp{\csname DP@#1\endcsname,\@currentlabel}%
  \else
    \edef\DPx@tmp{\@currentlabel}%
  \fi
  \global\expandafter\let\csname DP@#1\endcsname\DPx@tmp
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  \begingroup
    \let\DPx@curr\@empty
    \let\DPx@tmp\@empty
    \expandafter\expandafter\expandafter\comma@parse
    \expandafter\expandafter\expandafter{\csname DP@#1\endcsname}%
    \AssignedAux
    \ifx\DPx@curr\@empty
    \else
      \edef\DPx@tmp{\DPx@tmp-\DPx@curr}%
    \fi
    \global\expandafter\let\csname Assigned#1\endcsname\DPx@tmp
  \endgroup
  \typeout{ASSIGNED: \csname Assigned#1\endcsname}
}
\def\AssignedAux#1{%
  \ifx\DPx@tmp\@empty
    \def\DPx@tmp{#1}%
    \count@=#1\relax
  \else
    \advance\count@\@ne
    \ifnum#1=\count@
      \def\DPx@curr{#1}%
    \else
      \count@=#1\relax
      \ifx\DPx@curr\@empty
        \edef\DPx@tmp{\DPx@tmp,#1}%
      \else
        \edef\DPx@tmp{\DPx@tmp-\DPx@curr,#1}%
        \let\DPx@curr\@empty
      \fi
    \fi
  \fi
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}\Assign{fred}
  \item Strawberries \Assign{julie}
  \item Pears \Assign{julie}
  \item Lemons \Assign{fred}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

结果:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 1,3,4
ASSIGN: 2,4,5
ASSIGN: 2,4,5,6
ASSIGN: 1,3,4,7
ASSIGNED: 1,3-4,7
ASSIGNED: 2,4-6

答案2

语法\def\Assigned#1{}不正确。正确的方法是\expandafter\def\csname Assigned#1\endcsname{}。这样您的代码就可以编译了。此外,\edef是本地化的,无法在更高级别访问。将其更改为 可以\xdef解决这个问题。

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{\expandafter\def\csname Assigned#1\endcsname{\csname DP@#1\endcsname}
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

日志文件包含:

ASSIGN: 1
ASSIGN: 2
ASSIGN: 1,3
ASSIGN: 2,4
ASSIGN: 2,4,5
ASSIGNED: 1,3
ASSIGNED: 2,4,5

答案3

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  \csname DP@#1\endcsname
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

作业

对更新后问题的回复

要获取名称以及产品编号:

\documentclass{article}
\makeatletter
\def\Assign#1{% if \DP@#1 is defined append to it otherwise create it
  \ifcsname DP@#1\endcsname\def\DP@tmp{\csname DP@#1\endcsname,\@currentlabel}
  \else\def\DP@tmp{\@currentlabel}
  \fi
  \expandafter\xdef\csname DP@#1\endcsname{\DP@tmp}
  \typeout{ASSIGN: \csname DP@#1\endcsname}
}
\def\Assigned#1{%
  #1: \csname DP@#1\endcsname
                \typeout{ASSIGNED: \csname DP@#1\endcsname}
}
\makeatother

\begin{document}

\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

\Assigned{fred}   % should print 1,3
\Assigned{julie}  % should print 2,4,5

\end{document}

按姓名分配任务

答案4

您可能会喜欢 LaTeX3 版本;

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\Assign}{m}
 {
  \andrew_assign:n { #1 }
 }
\NewDocumentCommand{\Assigned}{m}
 {
  \andrew_assigned:n { #2 }
 }

% syntactic sugar for shortening code
\cs_new:Npn \__andrew_seq:n #1
 {
  g_andrew_assignee_#1_seq
 }

\cs_new_protected:Npn \andrew_assign:n #1
 {% if the assignee is not yet defined, create a sequence
  \seq_if_exist:cF { \__andrew_seq:n { #1 } }
   {
    \seq_new:c { \__andrew_seq:n { #1 } }
   }
  % globally add the item to the assignee's sequence
  \seq_gput_right:cv { \__andrew_seq:n { #1 } } { @currentlabel }
 }

\cs_new:Npn \andrew_assigned:n #1
 {% print the assignee's items separated by a comma
  \seq_use:cn { \__andrew_seq:n { #1 } } { ,~ }
 }

\cs_generate_variant:Nn \seq_gput_right:Nn { cv }
\cs_generate_variant:Nn \seq_use:Nn { c }

\ExplSyntaxOff

\begin{document}
\begin{enumerate}
  \item Apples \Assign{fred}
  \item Oranges \Assign{julie}
  \item Bananas \Assign{fred}
  \item Mangos \Assign{julie}
  \item Strawberries \Assign{julie}
\end{enumerate}

Fred has \Assigned{fred}   % should print 1,3

Julie has \Assigned{julie}  % should print 2,4,5

\end{document}

相关内容