在 foreach 循环中使用列表

在 foreach 循环中使用列表

我正在尝试使绘图更加自动化,并尝试在兴趣点附近强制样本的存在。

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\alist(\Wmax)}
    \foreach \i in {(\Wmin):(0.5*1/#2),(0.5*1/#2):(2*1/#2),(2*1/#2):(0.5*1/#3),(0.5*1/#3):(2*1/#3),(2*1/#3):(\Wmax)}
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

这是 MWE,它起作用了。但我想替换

    \foreach \i in {(\Wmin):(0.5*1/#2),(0.5*1/#2):(2*1/#2),(2*1/#2):(0.5*1/#3),(0.5*1/#3):(2*1/#3),(2*1/#3):(\Wmax)}
        \addplot [domain=\i,samples=50]

经过

    \foreach \i in {\alist}
        \addplot [domain=\i,samples=50]

但它无法编译。列表创建来自我在这里找到的代码,它似乎\alist包含了好东西,但我似乎无法在 foreach 中使用它。

如果你想帮助我,我认为你可以做两件事:

  • 帮助我利用(完成) \alist中的工作\foreach
    • 答案 1:将表达式更改\foreach \i in {\alist}\foreach \i in \alist
    • \usepackage{listofitems}答案 2:使用类似这样的数组\readlist\alistlst{\alist}% \foreachitem\i\in\alistlst[]{%
  • 找到一种简单的方法来生成采样,例如samples at

先感谢您。

如果您对结果感到好奇:

阴谋的结果

答案1

编辑1:

手册.pdf关于\foreach⟨list⟩论点:

同样,在最简单的情况下,⟨list⟩ 它是一个用花括号括起来的逗号分隔的值列表 或者它是包含此类值列表的宏的名称。任何东西都可以用作值,但最有可能的是数字。

短语“包含此类值列表的宏的名称”有点误导,但该语句的意思是:

如果⟨list⟩不是嵌套在一对花括号之间,然后⟨list⟩被视为一个控制序列,其顶层扩展形成所讨论的值的逗号分隔列表。

因此,您需要做的就是省略周围的花括号\alist
只需将表达式更改为。\foreach \i in {\alist}\foreach \i in \alist

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\alist(\Wmax)}
    \foreach \i in \alist % <- curly braces surrounding \alist are omitted here.
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

在此处输入图片描述


上一个答案:

一个问题是\foreach \i in {\alist}宏在执行\alist之前没有被展开。\foreach

因此\foreach不会采用\alist的扩展,即,不会采用标记序列(\Wmin):(0.5*1/#2),(0.5*1/#2):(2*1/#2),(2*1/#2):(0.5*1/#3),(0.5*1/#3):(2*1/#3),(2*1/#3):(\Wmax) 作为其参数,而是采用单个标记\alist作为其参数。

您可以在执行之前应用\expandafter\PassFirstToSecond\expandafter{\alist}{\foreach...}-trickery 来扩展:\alist\foreach

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newcommand\PassFirstToSecond[2]{#2{#1}}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\alist(\Wmax)}
    \expandafter\PassFirstToSecond\expandafter{\alist}{\foreach \i in }%
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

在此处输入图片描述

另一种方法:如果\alist只是将临时宏放在\noexpand\foreach \noexpand\i最后的 中\xdef\alist,然后调用\alist而不是\foreach

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\noexpand\foreach \noexpand\i in {\alist(\Wmax)}}
    \alist
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

定义:

\def\foreachinlist#1#2{\expandafter\foreachinlistA\expandafter#1\expandafter{#2}}
\def\foreachinlistA#1{\foreach#1in}

并使用:

\foreachinlist \i \alist

在您的示例中:

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\def\foreachinlist#1#2{\expandafter\foreachinlistA\expandafter#1\expandafter{#2}}
\def\foreachinlistA#1{\foreach#1in}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\alist(\Wmax)}
    \foreachinlist \i \alist
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

答案3

在以下人员的帮助下listofitems

\documentclass{standalone}
\usepackage{pgfplots,listofitems}
\pgfplotsset{compat=1.16}

\newcommand*{\TracStack}[4]{
    \gdef\alist{(\Wmin):}
    \foreach \i in {#2,#3} {
     \xdef\alist{\alist(0.5*1/\i),(0.5*1/\i):(2*1/\i),(2*1/\i):}
    }
    \xdef\alist{\alist(\Wmax)}
    \readlist\alistlst{\alist}% <-- READS \alist ITEMS INTO \alistlst LIST
    \foreachitem\i\in\alistlst[]{% <-- OPERATES ON SUCCESSIVE \alistlst ITEMS
        \addplot [domain=\i,samples=50]
        { 
            -(10*(log10(#2^2*x^2+1)))
            -(10*(log10(#3^2*x^2+1)))
        }[#4];
    }
}

\begin{document}
    \begin{tikzpicture} 
        \def\Wmax{10^(2)}
        \def\Wmin{10^(-1)}
        \begin{semilogxaxis}
        [ymin=-90,ymax=80]
        \TracStack{10}{10}{0.1}{}
        \TracStack{100}{5}{0.2}{red}
        \end{semilogxaxis}
    \end{tikzpicture}
\end{document}

在此处输入图片描述

答案4

你可以避开所有的\xdef业务。

这里的名称\foreachiinlist完全是任意的,并且一旦执行宏,其含义就会消失。所以你\alist再也不会遇到麻烦了。

\documentclass{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}

\newcommand{\TracStackPoints}[1]{(0.5*1/#1),(0.5*1/#1):(2*1/#1),(2*1/#1):}

\newcommand*{\TracStack}[4]{%
  \begingroup
  \edef\foreachiinlist{%
    \endgroup
    \unexpanded{\foreach \i in }%
    {(\Wmin):\TracStackPoints{#2}\TracStackPoints{#3}(\Wmax)}%
  }%
  \foreachiinlist {
    \addplot [domain=\i,samples=50]
      { 
       -(10*(log10(#2^2*x^2+1)))
       -(10*(log10(#3^2*x^2+1)))
      }[#4];
  }%
}

\begin{document}

\begin{tikzpicture} 
  \def\Wmax{10^(2)}
  \def\Wmin{10^(-1)}
  \begin{semilogxaxis}[ymin=-90,ymax=80]
    \TracStack{10}{10}{0.1}{}
    \TracStack{100}{5}{0.2}{red}
  \end{semilogxaxis}
\end{tikzpicture}

\end{document}

在此处输入图片描述

相关内容