改变框外的列表

改变框外的列表

我使用本教程中的 prune list 命令生成无重复的随机数以避免在生成随机序列时出现重复。但是,如果我尝试在框架框中使用此命令,它不起作用。在minipage环境中也是如此。为什么会发生这种情况?

\documentclass[a4paper,14pt]{extreport}
\usepackage{tikz}

\newcommand\lengthof[1]{\csname pgfmath@randomlist@#1\endcsname}
\newcommand\nthof[2]{\csname pgfmath@randomlist@#2@#1\endcsname}

\def\mylist{{one}{two}{three}{four}{five}}
\pgfmathdeclarerandomlist{mynum}{\mylist} %Define the list 

\makeatletter
 \def\prunelist#1{% Define prunelist command
  \expandafter\edef\csname pgfmath@randomlist@#1\endcsname
     {\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
  \count@\pgfmath@randomtemp 
  \loop
   \expandafter\let
   \csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
   \csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
   \ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
   \advance\count@\@ne
  \repeat}
\makeatother

\newcommand\prnrnd{%
\pgfmathrandomitem{\mynum}{mynum}\mynum %get and print item from list 
\prunelist{mynum} %prune list by selected item}

\begin{document}
\foreach \i in {1, ..., \lengthof{mynum}}%show list
{\par\textit{\nthof{\i}{mynum}}}\\

\fbox{\prnrnd}%extract item (item wasn't extracted!)
\foreach \i in {1, ..., \lengthof{mynum}}%show list
{\par\textit{\nthof{\i}{mynum}}}\\

\prnrnd%extract item
\foreach \i in {1, ..., \lengthof{mynum}}%show list
{\par\textit{\nthof{\i}{mynum}}}\\

\prnrnd%extract item
\foreach \i in {1, ..., \lengthof{mynum}}%show list
{\par\textit{\nthof{\i}{mynum}}}\\
\end{document}

enter image description here

答案1

您甚至不需要 来\fbox显示此效果;\prnrnd用括号括起来就足够了。解释是 的更改\prunelist仅限于当前组。在组之外(\fbox也形成一个组),您将返回到旧值, 的效果\prnrnd已被撤消。

这里有两种解决方案;我推荐第一个。

改变框外的列表

我建议修改您的\prnrnd命令,使其不打印元素,而只是将其存储在宏中。然后您可以在框外执行它并使用框内存储的元素。\prnrnd用以下定义替换。

\newcommand\nextrnd[2]%
  {\pgfmathrandomitem{\tmp}{#2}% select random element
   \edef#1{\tmp}% store random element in #1
   \prunelist{#2}%prune list by selected item
  }

\nextrnd{<var>}{<list>}将从中挑选并移除下一个随机元素<list>并将其存储在中<var>

为了使您的代码更易于阅读,我还定义了一个用于列出列表内容的宏。

\newcommand\showrndlist[1]%
  {\foreach \i in {1, ..., \lengthof{#1}}
     {\par\textit{\nthof{\i}{#1}}}%
   \bigskip
  }

这是完整的代码及其输出。

\documentclass{article}
\usepackage{pgffor}

\newcommand\lengthof[1]{\csname pgfmath@randomlist@#1\endcsname}
\newcommand\nthof[2]{\csname pgfmath@randomlist@#2@#1\endcsname}

\newcommand\nextrnd[2]%
  {\pgfmathrandomitem{\tmp}{#2}% select random element
   \edef#1{\tmp}% store random element in #1
   \prunelist{#2}%prune list by selected item
  }
\newcommand\showrndlist[1]%
  {\foreach \i in {1, ..., \lengthof{#1}}
     {\par\textit{\nthof{\i}{#1}}}%
   \bigskip
  }

\makeatletter
 \def\prunelist#1{% Define prunelist command
  \expandafter\edef\csname pgfmath@randomlist@#1\endcsname
     {\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
  \count@\pgfmath@randomtemp 
  \loop
   \expandafter\let
   \csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
   \csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
   \ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
   \advance\count@\@ne
  \repeat}
\makeatother

\begin{document}
\def\mylist{{one}{two}{three}{four}{five}}
\pgfmathdeclarerandomlist{mynum}{\mylist}% Define the list 

\showrndlist{mynum}

\nextrnd\rnd{mynum}% Store random element in \rnd and remove it from mynum
\fbox{\rnd}% The random element can be put inside a box
\showrndlist{mynum}

\nextrnd\rnd{mynum}% Store random element in \rnd and remove it from mynum
{\rnd}% ... or inside a group
\showrndlist{mynum}

\nextrnd\rnd{mynum}% Store random element in \rnd and remove it from mynum
\rnd
\showrndlist{mynum}
\end{document}

enter image description hereenter image description hereenter image description hereenter image description here

\prunelist使全球影响

您可以通过替换来使永久效果\prunelist超出组范围

\expandafter\edef

经过

\expandafter\xdef

\expandafter\let

经过

\expandafter\global\expandafter\let

这样定义就变成了

\makeatletter
 \def\prunelist#1{% Define prunelist command
  \expandafter\xdef\csname pgfmath@randomlist@#1\endcsname % <<< \edef changed to \xdef
     {\the\numexpr\csname pgfmath@randomlist@#1\endcsname-1\relax}
  \count@\pgfmath@randomtemp 
  \loop
   \expandafter\global\expandafter\let % <<< \expandafter\global added
   \csname pgfmath@randomlist@#1@\the\count@\expandafter\endcsname
   \csname pgfmath@randomlist@#1@\the\numexpr\count@+1\relax\endcsname
   \ifnum\count@<\csname pgfmath@randomlist@#1\endcsname\relax
   \advance\count@\@ne
  \repeat}
\makeatother

相关内容