
나는 쉼표로 구분된 목록 등을 반복하는 데 사용할 수 있는 다양한 방법에 대해 궁금했습니다. 특히 그들의 다양한 강점과 약점이 궁금했습니다. 즉, 나는 다음과 같은 사항에 대해 궁금했습니다(그러나 이 목록에만 국한되지는 않습니다).
- 확장 가능 여부,
- 빈 물건을 처리하는 방법,
- 불필요한 선행 및 후행 공백을 처리하는 방법
- 나중에 사용하기 위해 루프 내에서 정보를 저장하기 위해
\def
/를 사용할 수 있는지 또는 /를\edef
사용해야 하는지 여부.\gdef
\xdef
특별한 순서는 없지만, 제가 잘 알고 있는 루핑 방법 목록은 다음과 같습니다. 다음 목록에는 \current@item
반복에서 현재 항목의 형식을 지정하기 위해 하나의 인수를 사용하는 매크로가 나와 있습니다.
다음의 명령 사용 2ekernal
:
%% \@for
\def\@for@myloop#1{%%
\@for \x:=#1 \do{\current@item \x}}
%% \@tfor (not a comma separated list--probably shouldn't be here)
\def\@tfor@myloop#1{%%
\@tfor \x:=#1 \do{\if,\x\relax\else\current@item \x\fi}}
etoolbox
패키지 사용
%% `etoolbox`: need to be careful whether passed a macro:
%% in that case expansion may be necessary to that the
%% delimiters are visible to `\forcsvlist`
\def\etoolbox@myloop#1{%%
\expandafter\forcsvlist
\expandafter\current@item
\expandafter{#1}}
pgffor
패키지 사용
%% pgffor
\def\pgffor@myloop#1{%%
\foreach \x in {#1} {\current@item \x}}
홈브루 방법:
%% version a la `ae`
\def\@ae@myloop#1,#2\@nil{%%
\current@item{#1}%%
\expandafter\ifx\expandafter\relax\detokenize{#2}\relax\else
\@ae@myloop#2\@nil
\fi
}
\def\ae@myloop#1{%%
\@ae@myloop#1,\@nil
}
그런 다음 다음과 같은 다양한 방법도 있습니다 expl3
(상당히 많기 때문에 이것이 전부는 아닙니다).
\tl_map_inline:nn
\tl_map_function:Nn
\clist_map_inline:Nn
\seq_map_inline:Nn
다음은 이들 각각의 결과를 보여주는 MWE입니다(LaTeX3 버전 하나 포함).
\documentclass{article}
\usepackage[margin=0.5in,paperheight=15in]{geometry}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage{pgffor}
\usepackage{enumitem}
\makeatletter
\def\my@item@count{0}
\def\step@my@counter{\xdef\my@item@count{\number\numexpr\my@item@count+1\relax}}
%% \rules to emphasize how spaces are seen and treated!
\def\current@item#1{\step@my@counter\item \rule{0.4pt}{2ex}#1\rule{0.4pt}{2ex}}
%% `etoolbox`
\def\etoolbox@myloop#1{%%
\forcsvlist \current@item {#1}}
%% but if passed a macro, then it first needs to be expanded so the delimiters are visible to `\forcsvlist`. You'll need to write
%% \expandafter\forcsvlist \expandafter\current@item \expandafter{#1}}
%% \@for
\def\@for@myloop#1{%%
\@for \x:=#1 \do{\current@item \x}}
%% \@tfor
\def\@tfor@myloop#1{%%
\@tfor \x:=#1 \do{\current@item \x}}
%% pgffor
\def\pgffor@myloop#1{%%
\foreach \x in {#1} {\current@item \x}}
%% version a la `ae`
\def\@ae@myloop#1,#2\@nil{%%
\current@item{#1}%%
\expandafter\ifx\expandafter\relax\detokenize{#2}\relax\else
\@ae@myloop#2\@nil
\fi
}
\def\ae@myloop#1{%%
\@ae@myloop#1,\@nil
}
\def\listoffruit#1#2#3{%%
\def\my@item@count{0}%%
\noindent
List of type \texttt{#1}: \parbox[t]{3in}{\raggedright#3}
\begin{itemize}[topsep=4pt,itemsep=2pt]
\csname#1@myloop\endcsname{#2}%%
\end{itemize}
Total number of bulleted items: \my@item@count
\par \vspace{2ex}\hrule\par \vspace{2ex}
}
\ExplSyntaxOn
\NewDocumentCommand{\expl@myloop}{ m }
{
\clist_map_inline:nn{#1}{\current@item {##1}}
}
\ExplSyntaxOff
\makeatother
\def\apples{apples}
\def\bananas{bananas}
\def\cherries{cherries}
\begin{document}
\listoffruit{etoolbox}{apples,, oranges, bananas ,cherries}{Ignores leading spaces and empty items. Trailing spaces not ignored.}
\listoffruit{@for}{apples,, oranges, bananas ,cherries}{Empty lines and trailing or leading spaces not ignored. Something goes on with last item in list.}
\listoffruit{@tfor}{\apples,{} {oranges}\bananas\cherries}{Spaces ignored, all other token respected, bracketed tokens treated as one.}
\listoffruit{pgffor}{apples,, oranges, bananas ,cherries}{Ignores leading spaces, empty items and trailing spaces not ignored.}
\listoffruit{ae}{apples,, oranges, bananas ,cherries}{Leading or trailing spaces not ignored. Empty items not ignored.}
\listoffruit{expl}{apples,, oranges, bananas ,cherries}{Trailing or leading spaces ignored. Empty items ignored.}
\end{document}
내가 알고 있는 문제:
- 확장이 불가능하다고 생각합니다
\@for
. \cslist_map_inline:nn
확장 가능하지만 제한이 있습니다. 즉, -type 인수에서는 확장할 수 없습니다f
.pgffor
\foreach
그룹 내에서 의 루프가 실행되었습니다. 따라서 나중에 사용할 수 있도록 그룹 내의 정보를 사용하거나 저장\gdef
해야 합니다 .\xdeg
나는 여기에 제시된 다른 루프 중 어떤 것이 비슷한지 완전히 조사하지 않았습니다.결점(단어 선택이 올바른지 확실하지 않습니다). 확장이 가능한지 아닌지는 잘 모르겠습니다\foreach
.- 일부 메서드는 매크로를 통해 명시적으로 전달되든 암시적으로 전달되든 목록을 꽤 훌륭하게 처리합니다. 예를 들어,
pgffor
's는\foreach
매크로를 통해 전달된 목록으로 무엇을 해야 하는지 알고 있습니다. 을(를) 먼저 확장하려면 해당 매크로etoolbox
가\forcsvlist
필요합니다. 따라서 a에 대한 첫 번째 그림이\forcslist
그만큼 복잡합니다.
그래서 제가 여기서 관심을 갖는 것은 다음과 같습니다.
- 이 게시물의 시작 부분에 항목별로 여기에 제시된 다양한 접근 방식의 강점과 약점을 다루는 응답이지만 다른 중요한 문제를 인식하지 못할 수 있으므로 반드시 이러한 제안으로 제한되지는 않습니다. 예를 들어, 어느 것이 실제로 확실하지 않습니다. 확장 가능합니다.
- 알려진 약점 및 강점과 함께 항목 목록을 반복하는 다른 방법을 소개하는 응답입니다.
- 확장 가능한 컨텍스트에서 이러한 루프를 사용하려는 현실적인 예를 설명할 수 있는 응답
- 나중에 사용하기 위해 그룹 내에서 수집된 정보를 저장하는 방법을 보여주는 응답입니다.
답변1
나는 다른 정의를 제안한다.\current@item
\def\current@item#1{%
\stepcounter{item@count}
\item $|$#1$|$\ $|$\texttt{\detokenize{#1}}$|$%
}
따라서 출력에는 실제로 인수로 전달된 내용도 표시됩니다. 그리고 복잡한 관리를 \my@item@count
간단한 카운터로 바꾸었습니다. \@tfor
쉼표로 구분된 목록용으로 설계되지 않은 다른 도구인 에 대해서는 언급하지 않습니다 .
etoolbox
:\forcsvlist
후행 공백을 제거하지 않습니다. 당신의 정의는 너무 복잡합니다. 왜냐하면%% `etoolbox` \def\etoolbox@myloop#1{%% \forcsvlist\current@item{#1}}
충분합니다. 항목은 명시적으로 전달됩니다.
\@for
LaTeX 커널에 정의된 기본 도구입니다. 선행 및 후행 공백은 제거되지 않습니다. 항목은\x
다음으로 사용되는 제어 시퀀스 로 전달됩니다\@for
.\foreach
후행 공백은 제거되지 않습니다. 항목은\x
다음으로 사용되는 제어 시퀀스 로 전달됩니다\foreach
.ae
\@for
확장을 통해 작동하지만 기본적으로 와 같습니다 . 선행 및 후행 공백은 제거되지 않습니다. 항목은 명시적으로 전달됩니다.expl
선행 및 후행 공백뿐만 아니라 빈 항목도 제거합니다. 항목은 명시적으로 전달됩니다.
\documentclass{article}
\usepackage[margin=0.5in,paperheight=15in]{geometry}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage{pgffor}
\usepackage{enumitem}
\makeatletter
\newcounter{item@count}
%% \rules to emphasize how spaces are seen and treated!
\def\current@item#1{%
\stepcounter{item@count}
\item $|$#1$|$\ $|$\texttt{\detokenize{#1}}$|$%
}
%% `etoolbox`
\def\etoolbox@myloop#1{%%
\forcsvlist\current@item{#1}}
%% \@for
\def\@for@myloop#1{%%
\@for \x:=#1\do{\current@item \x}}
%% pgffor
\def\pgffor@myloop#1{%%
\foreach \x in {#1} {\typeout{pgf:\x}\current@item \x}}
%% version a la `ae`
\def\@ae@myloop#1,#2\@nil{%%
\current@item{#1}%%
\if\relax\detokenize{#2}\relax\else
\@ae@myloop#2\@nil
\fi
}
\def\ae@myloop#1{%%
\@ae@myloop#1,\@nil
}
\def\listoffruit#1#2{%%
\setcounter{item@count}{0}%%
\noindent
List of type \texttt{#1}
\begin{itemize}[topsep=4pt,itemsep=2pt]
\csname#1@myloop\endcsname{#2}%%
\end{itemize}
Total number of bulleted items: \arabic{item@count}%
\par \vspace{2ex}\hrule\par \vspace{2ex}
}
\ExplSyntaxOn
\NewDocumentCommand{\expl@myloop}{ m }
{
\clist_map_inline:nn{#1}{\current@item {##1}}
}
\ExplSyntaxOff
\makeatother
\begin{document}
\listoffruit{etoolbox}{apples,, oranges, bananas ,cherries}
\listoffruit{@for}{apples,, oranges, bananas ,cherries}
\listoffruit{pgffor}{apples,, oranges, bananas ,cherries}
\listoffruit{ae}{apples,, oranges, bananas ,cherries}
\listoffruit{expl}{apples,, oranges, bananas ,cherries}
\end{document}
expl3
빈 항목도 고려하는 또 다른 루프를 추가하겠습니다 .
\ExplSyntaxOn
\NewDocumentCommand{\seq@myloop}{ m }
{
\seq_set_split:Nnn \l_tmpa_seq { , } { #1 }
\seq_map_inline:Nn \l_tmpa_seq { \current@item {##1} }
}
\ExplSyntaxOff
(물론 사용은 \l_tmpa_seq
권장되지 않습니다. 새 변수를 할당하는 것이 좋습니다).
비교에는 의심의 여지가 없습니다. \foreach
가 우수한 유일한 곳은 와 같은 "불완전한 목록"을 처리하는 것입니다 1,2,...,20
.
답변2
LuaLaTeX:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{filecontents}
\begin{document}
\newcommand{\drawCircle}[1]{\tikz \draw (0,0) circle (#1);}
\begin{filecontents*}{testlua.lua}
for i=1,10 do
tex.print("\\drawCircle{",0.1*i,"}")
end
\end{filecontents*}
\directlua{dofile('testlua.lua')}
\end{document}