如果内层循环的重复次数不总是相同,那么如何编写嵌套循环?

如果内层循环的重复次数不总是相同,那么如何编写嵌套循环?

我正在写一份调查问卷。它列出了 16 个软件功能,参与者应该针对每个功能回答一次“我发现这个功能:非常重要 - 有点重要 - 一点也不重要”之类的问题。

在我们制作问卷时,功能和每个问题的措辞都会发生很大变化,因此每次都格式化所有内容并一遍又一遍地包含更改是疯狂的。相反,我创建了一个名为的命令,\featureanswers它接受一个参数(功能描述)并打印有关功能的问题。我使用这个命令和一个pgffor循环来创建问卷。

现在,我的老板决定我们必须更改编号。由于特征 7 和特征 8 是互斥的,因此它们应该被编号为特征 7a 和特征 7b。我找不到适合这种情况的好的解决方案。我尝试编写一个嵌套循环,但只成功编写了一个在每次运行内循环时都期望相同数量的元素的循环。

有什么想法可以让我自动处理这个问题吗?我知道我可以将其拆分为两个循环(7 之前和之后)并单独打印 7a 和 7b,但我想要一个更优雅的解决方案,它可以处理其他功能将来的更改。

这是当前版本的代码。它假设所有功能都相同(没有 7a 和 7b)。

\documentclass[a4paper,12pt]{article} 
\usepackage{pgffor}
\usepackage{amssymb}

\def\allfeatures{\fone,\ftwo,\fthree,\ffour,\ffive,\fsix,\fseven,\feight,\fnine,\ften,\feleven,\ftwelve,\fthirteen,\ffourteen,\ffifteen,\fsixteen}

\def\fone{redacted}
\def\ftwo{redacted}
\def\fthree{redacted}
\def\ffour{redacted}
\def\ffive{redacted}
\def\fsix{redacted}
\def\fseven{redacted}
\def\feight{redacted }
\def\fnine{redacted}
\def\ften{redacted}
\def\feleven{redacted}
\def\ftwelve{redacted}
\def\fthirteen{redacted}
\def\ffourteen{redacted}
\def\ffifteen{redacted}
\def\fsixteen{redacted}

\newcounter{featurecounter}
\setcounter{featurecounter}{0}
\newcommand{\featureanswers}[1]
{
\stepcounter{featurecounter}

    \vspace{18pt}
    {\bf Feature} \arabic{featurecounter} {#1}
    \begin{enumerate}
         \parbox{8cm}{\item I can envision a way this feature will be implemented.}
        \begin{tabular}{c c c c c}
            really well & & unsure & & not at all \\
            $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\
        \end{tabular}

        \parbox{4.5cm}{\item I think this feature is: }
            \begin{tabular}{c c c c c}
                very important & & slightly important & & not important \\
                $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\
            \end{tabular}

    \end{enumerate}
}

\begin{document}

\foreach \featureB in \allfeatures{
    \featureanswers{\featureB}
}

\end{document}

答案1

输入问题的语法看起来不错:

\features{
  1/First question \\
  2/Second question \\
  3/Third question \\
  4a/Fourth question A \\
  4b/Fourth question B \\
  5/Fifth question
}

数字可以是任何你想要的数字。完整示例代码如下:

\documentclass[a4paper,12pt]{article} 

\usepackage{amssymb}
\usepackage{xparse}
\NewDocumentCommand{\featureprint}{ >{\SplitList{/}} m }
  {\featureprintaux #1}
\NewDocumentCommand{\featureprintaux}{ m m }
  {\par
   \vspace{18pt}
   \textbf{Feature} #1. #2
    \begin{enumerate}
        \item\parbox[t]{8cm}{I can envision a way this feature will be implemented.}
        \begin{tabular}[t]{c c c c c}
            really well & & unsure & & not at all \\
            $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\
        \end{tabular}
        \item\parbox[t]{4.5cm}{I think this feature is: }
            \begin{tabular}[t]{c c c c c}
                very important & & slightly important & & not important \\
                $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\
            \end{tabular}
    \end{enumerate}
}
\ExplSyntaxOn
\NewDocumentCommand{\features}{ +m }
  {
   \seq_set_split:Nnn \l_feat_features_seq { \\ } { #1 }
   \seq_map_inline:Nn \l_feat_features_seq
     {
      \featureprint { ##1 }
     }
  }
\ExplSyntaxOff

\begin{document}

\features{
  1/First question \\
  2/Second question \\
  3/Third question \\
  4a/Fourth question A \\
  4b/Fourth question B \\
  5/Fifth question
}

\end{document}

在此处输入图片描述

答案2

您需要首先考虑正在使用的数据结构:

首先,你有一个包含以下特征的列表:

\def\alist{1,2,3,4,5,6,7,7a,8,9,10}

普通数字指向排版 A 行的宏,带有字母的宏指向排版 B 行的宏。

请注意,该列表仅包含指向保存信息的宏的指针,而不包含宏。让我们自动创建宏:

\def\Z{This is line A}
\def\ZZ{This is line B}         

\newcounter{ctr}
\setcounter{ctr}{0}
\loop
  \ifnum\thectr<11
    \expandafter\edef\csname feature@\thectr\endcsname{Feature \thectr\ Redacted\par \Z\par\Z\par }%
     \stepcounter{ctr}
\repeat
\expandafter\edef\csname feature@7a\endcsname{Feature 7a Redacted\par \ZZ\par\ZZ\par }%

接下来我们使用循环来访问它们:

\@for\next:=1,2,3,4,5,6,7,7a,8,9,10\do{%
   \csname feature@\next\endcsname
  }

量子电动力学

这是完整的 MWE。

\documentclass{article}
\makeatletter
\def\Z{This is line A}
\def\ZZ{This is line B}         

\newcounter{ctr}
\setcounter{ctr}{0}
\loop
  \ifnum\thectr<11
    \expandafter\edef\csname feature@\thectr\endcsname{Feature \thectr\ Redacted\par \Z\par\Z\par }%
     \stepcounter{ctr}
\repeat
\long\expandafter\edef\csname feature@7a\endcsname{Feature 7a Redacted\par \ZZ\par\ZZ\par }%

\begin{document}
\@for\next:=1,2,3,4,5,6,7,7a,8,9,10\do{%
   \csname feature@\next\endcsname
  }
\end{document}

答案3

以下是实现此目的的一种方法:\allfeatures元素本身可以是一个列表,这意味着添加部分(a)(b)等等...请注意,元素 7 是{\fsevenA,\fsevenB}

由于输入字符串中可以包含逗号,并且我们使用逗号作为列表分隔符,因此需要特殊处理。我发现的一个解决方案是对文本中的逗号使用宏:

\newcommand*{\Comma}{{,} }

也许可以通过一些\catcode技巧来避免这种情况,但这确实有效。

下面我注释掉了\enumerate包含这两个内容\parbox,因为不需要显示这里要解决的问题:

在此处输入图片描述

笔记:

  • 它们?似乎没有造成任何特殊问题。
  • 我使用该xstring包来测试当前列表中的成员数量,并且仅当列表中有多个成员时才添加字母标签。
  • 这需要将\stepcounter功能移至\foreach循环。

代码:

\documentclass[a4paper,12pt]{article} 
\usepackage{pgffor}
\usepackage{amssymb}
\usepackage{xstring}

\newcommand*{\Comma}{{,} }%

\def\allfeatures{\fone,\ftwo,\fthree,\ffour,\ffive,\fsix,{\fsevenA,\fsevenB},{\feight},\fnine,\ften,\feleven,\ftwelve,\fthirteen,\ffourteen,\ffifteen,\fsixteen}

\def\fone{This is the first feature}
\def\ftwo{This is the second feature}
\def\fthree{This is the third feature\Comma and happens to have a comma}
\def\ffour{This is the fourth feature}
\def\ffive{This is the fifth feature}
\def\fsix{This is the sixth feature}
\def\fsevenA{This is the first part of the seventh feature\Comma and has a ? and a comma}%  
%%Now, there are two features here, that are
\def\fsevenB{This is the second part of the seventh feature}%  provided as one group in 
%the list of \allfeatures .
\def\feight{This is the eighth feature\Comma maybe?}
\def\fnine{This is the ninth feature}
\def\ften{This is the tenth feature}
\def\feleven{This is the eleventh (I think?) feature}
\def\ftwelve{This is the twelveth feature}
\def\fthirteen{This is the thirteenth feature}
\def\ffourteen{This is the fourteenth feature}
\def\ffifteen{This is the fifteenth feature}
\def\fsixteen{This is the sixteenth feature}


\newcounter{featurecounter}
\newcounter{featureSubCounter}
\setcounter{featurecounter}{0}
\setcounter{featureSubCounter}{0}
\newcommand{\featureanswers}[2][2]{%
    \IfEq{#1}{0}{\arabic{featurecounter}}{\arabic{featurecounter}(\alph{featureSubCounter})}%
    \vspace{18pt}%
    {\bfseries ~Feature}  {#2}%

% Comment this out as output can still show that the problem being solved here works
%    \begin{enumerate}%
%         \parbox{8cm}{\item I can envision a way this feature will be implemented.}%
%        \begin{tabular}{c c c c c}%
%            really well & & unsure & & not at all \\%
%            $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\%
%        \end{tabular}%
%
%        \parbox{4.5cm}{\item I think this feature is: }%
%            \begin{tabular}{c c c c c}%
%                very important & & slightly important & & not important \\%
%                $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\%
%            \end{tabular}%
%    \end{enumerate}%
}

\begin{document}
\foreach \featureBList in \allfeatures{%
    \StrCount{\featureBList}{,}[\NumberOfItems]%
    \stepcounter{featurecounter}%
    \setcounter{featureSubCounter}{0}%
    \foreach \featureB in \featureBList{%
        \stepcounter{featureSubCounter}%
        \featureanswers[\NumberOfItems]{\featureB}%
    }%
}
\end{document}

答案4

Peter Grill 提供的答案很有趣,但如果某个功能包含逗号,它就会失效。根据他的回答,我创建了自己的版本。它看起来有点笨拙,但确实有效。我特别不喜欢它必须检查子功能是否以 开头的部分a,因此它不会倒回计数器。

正如您所见,逗号(不再用于控制结构)和问号(我现在用于控制)都不会破坏它。

我知道格式还不是很好,但稍后内容确定后我会对其进行改进。

\documentclass[a4paper,12pt]{article} 
\usepackage{pgffor}
\usepackage{amssymb}
\usepackage{xstring}

%We have to know which feature gets a special number. For this, we use a prefix. 0? for
 features with no special number, a? for the first subfeature of a question, then
 alphabetically for the next subfeatures. 
\def\allfeatures{0?\fone,0?\ftwo,0?\fthree,0?\ffour,0?\ffive,0?\fsix,a?\fsevenA,b?
\fsevenB,0?\feight,0?\fnine,0?\ften,0?\feleven,0?\ftwelve,0?\fthirteen,0?\ffourteen,0?
\ffifteen,0?\fsixteen}

\def\fone{This is the first feature}
\def\ftwo{This is the second feature}
\def\fthree{This is the third feature, and happens to have a comma}
\def\ffour{This is the fourth feature}
\def\ffive{This is the fifth feature}
\def\fsix{This is the sixth feature}
\def\fsevenA{This is the first part of the seventh feature, and has a ? and a comma}%  
Now, there are two features here, that are
\def\fsevenB{This is the second part of the seventh feature}%  provided as one group in 
the list of \allfeatures .
\def\feight{This is the eighth feature, maybe?}
\def\fnine{This is the ninth feature}
\def\ften{This is the tenth feature}
\def\feleven{This is the eleventh (I think?) feature}
\def\ftwelve{This is the twelveth feature}
\def\fthirteen{This is the thirteenth feature}
\def\ffourteen{This is the fourteenth feature}
\def\ffifteen{This is the fifteenth feature}
\def\fsixteen{This is the sixteenth feature}

\newcounter{featurecounter}
\setcounter{featurecounter}{0}
\newcommand{\featureanswers}[2]{%
    \arabic{featurecounter}#1.\ %
    \vspace{18pt}%
    {\bfseries ~Feature}  {#2}%
    \begin{enumerate}%
         \parbox{8cm}{\item I can envision a way this feature will be implemented.}%
        \begin{tabular}{c c c c c}%
            really well & & unsure & & not at all \\%
            $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\%
        \end{tabular}%

        \parbox{4.5cm}{\item I think this feature is: }%
            \begin{tabular}{c c c c c}%
                very important & & slightly important & & not important \\%
                $\square$ & $\square$ & $\square$ & $\square$ & $\square$ \\%
            \end{tabular}%
    \end{enumerate}%
}

\begin{document}
\foreach \featureB in \allfeatures{%
    \stepcounter{featurecounter}%
    \IfBeginWith{\featureB}{0?}{
       \featureanswers{}{\StrBehind{\featureB}{?}} 
    }
    {
        \IfBeginWith{\featureB}{a?}
        {}
        {\addtocounter{featurecounter}{-1}}
        \featureanswers{\StrBefore{\featureB}{?}}{\StrBehind{\featureB}{?}}
    }

}%
\end{document}

生成的格式

相关内容