업데이트된 질문에 대한 응답

업데이트된 질문에 대한 응답

본질적으로 목록을 생성하는 일부 매크로를 동적으로 정의하고 싶습니다 \ref. 이러한 매크로를 정의할 수 있는 것 같지만 인쇄할 수는 없습니다.

내 M(비)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(비)WE 라텍스는 아무런 문제가 없지만, 제가 이해할 수 없는 이유로 매크로 \Assigned가 확장되지 않습니다. , ... \expandafter을 1회 이상 사용하여 다양한 변형을 시도했지만 \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,4,5,6,8" 대신 "1,3-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}

관련 정보