\includegraphics 中无重复的随机数

\includegraphics 中无重复的随机数

我有 58 张 PDF 格式的图片。目前,每张都在单独的 PDF 中,例如等1.pdf2.pdf我想以随机顺序包含这 58 张图片,且不重复。

我找到了‘随机顺序,不重复’部分:生成无重复的随机数

坦率地说,这就是我所做的(最少的代码):

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

\begin{document}

%here is the bit from the link above to randomly draw a number from a list of integers without repetition
\def\declarenumlist#1#2#3{%
    \expandafter\edef\csname pgfmath@randomlist@#1\endcsname{#3}%
    \count@\@ne
    \loop
    \expandafter\edef
    \csname pgfmath@randomlist@#1@\the\count@\endcsname
    {\the\count@}
    \ifnum\count@<#3\relax
    \advance\count@\@ne
    \repeat}

%I want 58 numbers because I have 58 images
\declarenumlist{total}{1}{58}

%I try to include my pdf
\includegraphics{\pgfmathrandomitem\z{total}\z.pdf}

\end{document}

当然,这是行不通的,原因是我认为'\includegraphics 应该是一个文件名(宏扩展之后),而不是计算它的指令集',如如何包含随机图像?。我尝试按照这个问题建议的路线,通过做一个

\newcommand{\myrandomnumber}{\pgfmathrandomitem\z{total}\z}
\includegraphics{\myrandomnumber.pdf}

但这也不起作用。

请注意,如果需要,我可以将我的 58 张图像保存在同一个 pdf 中(它们是由 pdflatex 生成的)并使用\includepdf[pages={\pgfmathrandomitem\z{total}\z}]{images.pdf},但这也不起作用,我想是出于同样的原因。

有人知道发生了什么事吗(我想了解一下)以及如何解决我的问题?任何帮助都将不胜感激。

答案1

你应该把\makeatletter\makeatother放在定义周围\declarenumlist,并移到\pgfmathrandomitem\z{total}参数之外,就像\includegraphics

\pgfmathrandomitem\z{total}\includegraphics{\z.pdf}

然而,我建议一个不同的定义,\declarenumlist它不依赖于 TikZ/PGF 内部构建随机选择列表的实际方式。

在下面的代码中,生成从最低界限到最高界限的数字列表并将其作为参数输入\pgfmathdeclarerandomlist。循环非常相似,但如前所述,即使 TikZ/PGF 更改了这些列表的内部结构,宏仍将继续工作。

接下来我定义一个接口\includegraphics:该\randomincludegraphics命令接受要传递的选项\includegraphics,其强制参数是列表名称。

由于我没有可以使用的文件,我只是隐藏了要调用的真正宏并使用模拟文本来显示效果。

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

\begin{document}

\makeatletter
\def\declarenumlist#1#2#3{%
  \begingroup
  \count@=#2\relax
  \def\x{}%
  \loop
  \edef\x{\x{\the\count@}}%
  \ifnum\count@<#3\relax
    \advance\count@\@ne
  \repeat
  \edef\x{\endgroup
    \noexpand\pgfmathdeclarerandomlist{#1}{\x}%
  }\x
}
\makeatother

\newcommand{\randomincludegraphics}[2][]{%
  \begingroup
  \pgfmathrandomitem\z{#2}%
% Uncomment the following line for the production version  
%  \includegraphics[#1]{\z}%
% and remove the following line
  I want to include \texttt{\z.pdf} with options ``\texttt{#1}''%
  \endgroup
}

%I want 58 numbers because I have 58 images
\declarenumlist{total}{1}{58}

\randomincludegraphics{total}

\randomincludegraphics{total}

\randomincludegraphics[height=3cm,width=1cm]{total}

\end{document}

在此处输入图片描述


这是一个避免重复的版本;如果调用的次数超过可用项数,则使用随机重复(带有警告)。如果您想在其他时间使用它,则必须重新声明列表。

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

\begin{document}

\makeatletter
\def\declarenumlist#1#2#3{%
  \@ifundefined{c@#1@listcount}{\newcounter{#1@listcount}}{}%
  \setcounter{#1@listcount}{1}%
  \begingroup
  \count@=#2\relax
  \def\x{}%
  \loop
  \edef\x{\x{\the\count@}}%
  \global\expandafter\let\csname#1@\number\count@ @used\endcsname\relax
  \ifnum\count@<#3\relax
    \advance\count@\@ne
    \stepcounter{#1@listcount}%
  \repeat
  \edef\x{\endgroup
    \noexpand\pgfmathdeclarerandomlist{#1}{\x}%
  }\x
  \expandafter\mathchardef\csname #1@number\endcsname\value{#1@listcount}%
  \setcounter{#1@listcount}{0}%
}

\newcommand{\pgfmathuniquerandomitem}[2]{%
  \pgfmathrandomitem#1{#2}%
  \ifnum\value{#2@listcount}=\@nameuse{#2@number}%
    \@latex@warning{List #2 exhausted}%
  \else
    \@ifundefined{#2@#1@used}%
      {\stepcounter{#2@listcount}\global\@namedef{#2@#1@used}{used}}%
      {\pgfmathuniquerandomitem#1{#2}}%
  \fi
}

\makeatother

\newcommand{\randomincludegraphics}[2][]{%
  \begingroup
  \pgfmathuniquerandomitem\z{#2}%
% Uncomment the following line for the production version  
%  \includegraphics[#1]{\z}
% and remove the following line
  I want to include \texttt{\z.pdf} with options ``\texttt{#1}''
  \endgroup
}


%I want 58 numbers because I have 58 images
\declarenumlist{total}{1}{58}

\randomincludegraphics{total}

\randomincludegraphics{total}

\randomincludegraphics[height=3cm,width=1cm]{total}

\foreach\i in {1,...,58} { \randomincludegraphics{total}\endgraf }

\declarenumlist{total}{1}{58} % redeclare the list
\foreach\i in {1,...,58} { \randomincludegraphics{total}\endgraf }

\end{document}

2022 年更新

现在有更好的方法来完成同样的任务。

\documentclass[a4paper]{article}

\ExplSyntaxOn

% just for using all items
\NewDocumentCommand{\myforeach}{m +m}
 {
  \int_step_inline:nn { #1 } { #2 }
 }
%%%%

\NewDocumentCommand{\declarerandomlist}{mO{1}m}
 {% #1 = list name
  % #2 = start point (default 1)
  % #3 = end point
  \egreg_randomlist_declare:nnn { #1 } { #2 } { #3 }
 }

\NewDocumentCommand{\usefromrandomlist}{mm}
 {% #1 = list name
  % #2 = template
  \egreg_randomlist_use:nn { #1 } { #2 }
 }

\cs_new_protected:Nn \egreg_randomlist_declare:nnn
 {
  \seq_clear_new:c { l_egreg_randomlist_#1_seq }
  \bool_do_until:nn { \int_compare_p:n { \seq_count:c { l_egreg_randomlist_#1_seq } = #3-#2+1 } }
   {
    \seq_put_left:cx { l_egreg_randomlist_#1_seq } { \int_rand:nn { #2 } { #3 } }
    \seq_remove_duplicates:c { l_egreg_randomlist_#1_seq }
   }
 }

\cs_new_protected:Nn \egreg_randomlist_use:nn
 {
  \cs_set:Nn \__egreg_randomlist:n { #2 }
  \seq_if_empty:cTF { l_egreg_randomlist_#1_seq }
   {
    \msg_warning:nnn { randomlist } { exhausted } { #1 }
   }
   {
    \seq_pop_left:cN { l_egreg_randomlist_#1_seq } \l__egreg_randomlist_item_tl
    \__egreg_randomlist:V \l__egreg_randomlist_item_tl
   }
 }

\tl_new:N \l__egreg_randomlist_item_tl
\cs_new_protected:Nn \__egreg_randomlist:n { } % initialize
\cs_generate_variant:Nn \__egreg_randomlist:n { V }

\msg_new:nnn { randomlist } { exhausted } {List ~ #1 ~ exhausted}


\ExplSyntaxOff

\newcommand{\randomincludegraphics}[2][]{%
% Uncomment the following line for the production version  
%  \usefromrandomlist{#2}{\includegraphics[#1]{##1}
% and remove the following line
  \usefromrandomlist{#2}{I want to include \texttt{##1.pdf} with options ``\texttt{#1}''}
}

\begin{document}

\declarerandomlist{total}{5}

\randomincludegraphics{total}

\randomincludegraphics{total}

\randomincludegraphics[height=3cm,width=1cm]{total}

\myforeach{5}{\randomincludegraphics{total}\par}

\end{document}

除了名称之外,主要的区别在于

\usefromrandomlist

以列表名称和模板作为参数,其中#1代表随机列表中的当前项,因此可以执行

\usefromrandomlist{total}{\includegraphics{#1.pdf}}

或者抽象命令(如上面的代码),记住必须#1变成##1

在此处输入图片描述

相关内容