使用 \foreach 从文件中读取要迭代的数据

使用 \foreach 从文件中读取要迭代的数据

我有一个程序\foreach,它应该从文件中读取数据点。这些点的存储方式使得只需简单的复制粘贴即可。事实上,我不想做比复制粘贴更多的事情(如果可能的话)。我发现这\input行不通。有几个解决方案,但它们似乎比复制粘贴做得更多。有没有一种“简单”的方法来实现这一点?

文档.tex:

\documentclass[border=5mm]{standalone}
\usepackage{tikz}

\begin{document}
  \begin{tikzpicture}
  \foreach \from/\to in { \input{data}; } %input does not work...
  {\draw [->] \from -- \to;}

  \end{tikzpicture}
\end{document}

数据.dat:

{(1,1)}/{(3,3)},
{(-1,1)}/{(-3,3)},
{(1,-1)}/{(3,-3)}%

答案1

您可以使用catchfile

\begin{filecontents*}{\jobname.dat}
{(1,1)}/{(3,3)},
{(-1,1)}/{(-3,3)},
{(1,-1)}/{(3,-3)}%
\end{filecontents*}

\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\usepackage{catchfile}

\newcommand\loaddata[1]{\CatchFileDef\loadeddata{#1}{\endlinechar=-1}}

\begin{document}

\begin{tikzpicture}
\loaddata{\jobname.dat}
\foreach \from/\to in \loadeddata{\draw [->] \from -- \to;}
\end{tikzpicture}

\end{document}

这样\endlinechar=-1我们就有效地删除了已加载文件中的行尾。

enter image description here

答案2

有趣的方法。您遇到的问题源于每个段都在单独的行上,data.dat并且\foreach应该首先扩展参数。以下读取data.dat文件的内容(\loaddata命令基于这个答案) 并将每行附加到命令末尾\loadeddata,从而将所有数据放在一行上({(1,1)}/{(3,3)},{(-1,1)}/{(-3,3)},{(1,-1)}/{(3,-3)}%在您的示例中)。然后将其展开并用作调用中的参数\foreach

\begin{filecontents*}{data.dat}
{(1,1)}/{(3,3)},
{(-1,1)}/{(-3,3)},
{(1,-1)}/{(3,-3)}%
\end{filecontents*}
\documentclass[border=5mm]{standalone}
\usepackage{tikz}

\makeatletter
    \newread\dataread
    \def\loaddata#1{%
        \gdef\loadeddata{}%
        \openin\dataread=#1
        \begingroup\endlinechar=-1
        \@whilesw\unless\ifeof\dataread\fi{%
            \read\dataread to \dataline
            \edef\rslt{\noexpand\g@addto@macro\noexpand\loadeddata{\dataline}}%
            \rslt%expanded argument
        }%
        \endgroup
        \closein\dataread
    }%
\makeatother

\begin{document}
  \begin{tikzpicture}
    \loaddata{data.dat}
    \edef\expfor{\noexpand\foreach \noexpand\from/\noexpand\to in {\loadeddata}}
    \expfor{\draw [->] \from -- \to;}
  \end{tikzpicture}
\end{document}

result

答案3

为什么要重新发明轮子?文本合并可以使用以下代码合并数据:

\documentclass[tikz,border=10pt,multi]{standalone}
\usepackage{textmerg}
\begin{document}

\tikzset{%
  make line/.code args={#1/#2}{%
    \draw [->] #1 -- #2;
  },
}
\Fields{\myline}
\newcommand*\makeline[1]{%
  \tikzset{make line=#1}}
\begin{tikzpicture}
  \Merge{\jobname.dat}{
    \expandafter\makeline\expandafter{\myline}
  }
\end{tikzpicture}
\end{document}

data lines

相关内容