我有一个很大的文件索引(大约 600 页),每个文件条目都需要大量计算才能添加额外的链接。计算这些链接需要相当多的时间,而且由于每个文件名都出现在索引中的多个位置,因此这些链接在索引过程中会重复生成多次。
我目前的方法是将与每个链接相关的数据缓存在 中def
,但即使这样,运行也需要大约 6 个小时,而且这个时间会随着时间的推移而增加。我的想法是将此输出缓存在 中\savebox
,但基于Savebox 相当于 \csname?,看来这不是一个好办法。
主要问题:
如果我不应该使用\savebox
s,我还能如何实现类似的功能,即缓存输出(至少针对几千种不同的情况)?例如,假设\MyComplicatedCode
下面的 MWE 中的宏要复杂得多。除了调整之外,我还能做什么\MyComplicatedCode
,并且能够重用输出而无需重新计算它?
即使我完全理解扩展,我认为尝试扩展代码以便仅存储要添加的最终链接仍需要大量工作。
将代码排版成 .pdf 也不起作用,因为该代码会生成指向其他文件的链接。
子问题:
- 允许的 s数量限制是多少
\savebox
? - 可以通过改变一些参数来增加这些吗?
笔记:
- 我目前需要大约 1,500
\savebox
秒,并且随着时间的推移可能会增加到大约 5,000 秒。
参考:
代码:
由于使用\savebox
不是一个好主意,因此这个 MWE 并不那么重要。在煮熟的下面的例子中,我正在缓存从给定的分层文件名中提取的文件的名称。如果我创建一个,该示例可以正常工作\def
,但我似乎无法使用实现相同的功能\savebox
。目前产生的结果如下:
\documentclass{article}
\usepackage{pgffor}
\usepackage{xstring}
\newcommand*{\MyFileNames}{%
../../DirNameA/FileA1.tex,%
../../DirNameA/FileA2.tex,%
../../DirNameB/FileB1.tex,%
../../DirNameB/FileB2.tex%
}%
\newcommand*{\MyComplicatedCode}[4][1]{%
\StrBehind[#1]{#2}{#3}[#4]%
}%
\begin{document}
%% Create \newcommands
\foreach \X in \MyFileNames {%
\MyComplicatedCode[3]{\X}{/}{\ExtractedFileName}%
\expandafter\xdef\csname MyCommand\X\endcsname{File Name = \ExtractedFileName}%
%\par\string\MyCommand\X: \expandafter\csname MyCommand\X\endcsname
}%
%% Now use the \newcommands
Command ../../DirNameB/FileB1.tex:
\expandafter\csname MyCommand../../DirNameB/FileB1.tex\endcsname
\bigskip
\foreach \X in \MyFileNames {%
\MyComplicatedCode[3]{\X}{/}{\ExtractedFileName}%
\expandafter\newsavebox\csname MySaveBox\X\endcsname%
\expandafter\savebox\csname MySaveBox\X\endcsname{Savebox Value = \ExtractedFileName}%
}%
%% Now use the \savebox
Savebox ../../DirNameB/FileB1.tex:
\expandafter\usebox\csname MySaveBox../../DirNameB/FileB1.tex\endcsname%
\end{document}
答案1
您需要\X
在将其传递给字符串拆分函数之前进行扩展,并且如果使用循环结构,则需要使框分配全局化。
\documentclass{article}
\usepackage{pgffor}
\usepackage{xstring}
\newcommand*{\MyFileNames}{%
../../DirNameA/FileA1.tex,%
../../DirNameA/FileA2.tex,%
../../DirNameB/FileB1.tex,%
../../DirNameB/FileB2.tex%
}%
\newcommand*{\MyComplicatedCode}[4][1]{%
\StrBehind[#1]{#2}{#3}[#4]%
}%
\begin{document}
%% Create \newcommands
\foreach \X in \MyFileNames {%
\MyComplicatedCode[3]{\X}{/}{\ExtractedFileName}%
\expandafter\xdef\csname MyCommand\X\endcsname{File Name = \ExtractedFileName}%
%\par\string\MyCommand\X: \expandafter\csname MyCommand\X\endcsname
}%
%% Now use the \newcommands
Command ../../DirNameB/FileB1.tex:
\expandafter\csname MyCommand../../DirNameB/FileB1.tex\endcsname
\bigskip
\foreach \X in \MyFileNames {%
\edef\tmp{\noexpand\MyComplicatedCode[3]{\X}{/}{\noexpand\ExtractedFileName}}%
\tmp
\expandafter\newsavebox\csname MySaveBox\X\endcsname%
\global\expandafter\setbox\csname MySaveBox\X\endcsname\hbox{Savebox Value = \ExtractedFileName}%
}%
%% Now use the \savebox
Savebox %../../DirNameB/FileB1.tex:
\expandafter\usebox\csname MySaveBox../../DirNameB/FileB1.tex\endcsname%
\end{document}
虽然您可能应该只使用宏而不是框来实现这一点。或者您可以使用单个框,这取决于它们的使用方式。为每个框使用单独的寄存器有点浪费,但它可以轻松地以任意顺序访问各个条目。如果您实际上要按顺序处理所有项目,则可以将它们存储在一个框中。(无论如何,您都可以将它们存储在一个框中,但访问除第一个或最后一个之外的项目可能会变慢)