如何创建 dims 数组?

如何创建 dims 数组?

expl3 支持 int 数组。但是 dims 数组呢?

我需要一个整数索引数组变量,用于保存 dim 值。数组大小应该能够随时增长,而不是提前知道(我不知道它将保存多少 dim 值,大小取决于自定义环境的嵌套级别)。例如,如果计数器为 1,则数组大小为 1;如果计数器增长到 3,则数组应该增长到 3 个索引。

我需要类似下面的索引变量myDim

myDim[1]=5.0pt
myDim[2]=7.35pt
...

编辑:

% \myDim = 0 here
\begin{myEnv} % myDim[1] = 5.0pt; current index = 1
  \begin{myEnv} % myDim[2] = 7.35pt; current index = 2
  \end{myEnv} % current index = 1
\end{myEnv} % current index = 0

答案1

不能intarray改变大小,并且对它的分配始终是全局的,因此您不能利用环境分组来模拟这样的行为(至少不容易)。的文档l3intarray确实说:

intarray因此,在需要快速访问的情况下,建议使用数据。

但大多数情况下并非如此。如果您不打算使用包含数千个元素的数组并访问这些元素数千次,那么变量seq可能就足够了。

这是一个特别指定一种数据类型的实现array,它提供与 大致相同的接口,l3intarray但底层使用 的数据类型expl3seq

接口:

  • \array_new:N ⟨array var⟩— 创建一个⟨array var⟩没有元素的新变量。
  • \array_zero:N ⟨array var⟩— 将所有元素设置为零⟨array var⟩
  • \array_allocate:Nn ⟨array var⟩ {⟨num items⟩}— 将 分配⟨array var⟩⟨num items⟩,所有 都等于0pt。 中已有的项目⟨array var⟩保持不变,因此可以多次使用。
  • \array_deallocate:N ⟨array var⟩— 设置⟨array var⟩为没有元素。
  • \array_count:N ⟨array var⟩★ — 扩展为 中的元素数量⟨array var⟩
  • \array_item:Nn ⟨array var⟩ {⟨index⟩}⟨index⟩★ — 扩展到位置存储的维度⟨array var⟩。如果⟨index⟩大于 的大小⟨array var⟩,则函数扩展为零。如果⟨index⟩小于零,则索引从数组末尾开始计算。
  • \array_set:Nnn ⟨array var⟩ {⟨index⟩} {⟨dimen⟩}⟨index⟩— 设置的位置⟨array var⟩以包含⟨dimen⟩。如果⟨array var⟩不包含⟨index⟩,则元素将分配(包含\array_allocate:Nn)直到⟨index⟩存在。
  • \array_put_left:Nn ⟨array var⟩ {⟨dimexpr⟩}— 在末尾添加一个项目⟨array var⟩并放入⟨dimexpr⟩其中。
  • \array_put_right:Nn ⟨array var⟩ {⟨dimexpr⟩}— 在 开头添加一个项目⟨array var⟩并放入⟨dimexpr⟩其中。
  • \array_set_from_clist:Nn ⟨array var⟩ {⟨clist⟩}— 设置⟨array var⟩以包含 的项目⟨clist⟩
  • \array_log:N ⟨array var⟩— 写入⟨array var⟩日志文件。
  • \array_show:N ⟨array var⟩— 显示⟨array var⟩在命令窗口中。

标有★的功能完全可扩展。所有分配都是本地的(如果您需要全局分配,请在评论中询问),除了\array_new:N创建⟨array var⟩全局的。

代码如下:

\RequirePackage{filecontents}
\begin{filecontents}{bparray.sty}
\RequirePackage{expl3}
\ProvidesExplPackage{bparray}{2019-06-29}{0.1}{Array data type for expl3 (PHO)}
\cs_new_eq:NN \array_new:N \seq_new:N
\cs_new_eq:NN \array_count:N \seq_count:N
\cs_new_eq:NN \array_item:Nn \seq_item:Nn
\cs_new_eq:NN \array_deallocate:N \seq_clear:N
\cs_new_eq:NN \array_show:N \seq_show:N
\cs_new_eq:NN \array_log:N \seq_log:N
\cs_new_eq:NN \array_put_right:Nn \seq_put_right:Nn
\cs_new_eq:NN \array_put_left:Nn \seq_put_left:Nn
\cs_new_protected:Npn \array_allocate:Nn #1#2
  {
    \int_step_inline:nnn { \array_count:N #1 + 1 } { #2 }
      { \exp_args:NNx \array_put_right:Nn #1 { \dim_use:N \c_zero_dim } }
  }
\cs_new_protected:Npn \array_set:Nnn #1#2
  {
    \int_compare:nNnT {#2} > { \array_count:N #1 }
      { \array_allocate:Nn #1 {#2} }
    \__array_set_item:Nnn #1 {#2}
  }
\cs_new_protected:Npn \__array_set_item:Nnn #1
  { \exp_after:wN \__array_item:wNn #1 \q_stop #1 }
\cs_new_protected:Npn \__array_item:wNn \s__seq #1 \q_stop #2#3#4
  {
    \exp_args:Nf \__array_item:nnwn
      { \exp_args:Nf \__seq_item:nN { \int_eval:n {#3} } #2 } { }
    #1
    \prg_collect_point:
    \__array_replace_item:Nn #2 {#4}
    \prg_break: \__seq_item:n { }
    \prg_break_point:
  }
\cs_new_protected:Npn \__array_item:nnwn #1#2#3 \__seq_item:n #4
  {
    #3
    \int_compare:nNnTF {#1} = 1
      {
        \tl_set:Nn \l__array_internal_tl {#2}
        \prg_break_collect:Nw \__array_set_item_end:n
      }
      {
        \exp_args:Nf \__array_item:nnwn
          { \int_eval:n { #1 - 1 } }
          { #2 \__seq_item:n {#4} }
      }
  }
\cs_new_protected:Npn \__array_set_item_end:n #1
  { \exp_args:NV \__array_set_item_end:nnwn \l__array_internal_tl {#1} }
\cs_new_protected:Npn \__array_set_item_end:nnwn #1 #2 \__array_replace_item:Nn #3 #4
  {
    \tl_set:Nx #3
      {
        \s__seq
        \exp_not:n {#1}
        \exp_not:N \__seq_item:n { \dim_eval:n {#4} }
        \exp_not:n {#2}
      }
    \prg_break:
  }
\cs_new_eq:NN \__array_replace_item:Nn \use_none:nn
\cs_new:Npn \prg_break_collect:Nw #1 #2 \prg_collect_point: { #1{#2} }
\cs_new_eq:NN \prg_collect_point: \prg_do_nothing:
\cs_new_protected:Npn \array_zero:N #1
  { \exp_args:Nf \__array_zero:nN { \array_count:N #1 } #1 }
\cs_new_protected:Npn \__array_zero:nN #1#2
  {
    \array_deallocate:N #2
    \array_allocate:Nn #2 {#1}
  }
\cs_new_protected:Npn \array_set_from_clist:Nn #1#2
  {
    \array_deallocate:N #1
    \clist_map_inline:nn {#2}
      { \exp_args:NNx \array_put_right:Nn #1 { \dim_eval:n {##1} } }
  }
\end{filecontents}

以及测试文档:

\documentclass{article}
\usepackage{bparray}
\begin{document}
\ExplSyntaxOn
\array_new:N \l_bp_array
\array_log:N \l_bp_array \array_allocate:Nn \l_bp_array { 3 }
\array_log:N \l_bp_array \array_set:Nnn \l_bp_array { 5 } { 1 pt + 2.141592 pt }
\array_log:N \l_bp_array \array_zero:N \l_bp_array
\array_log:N \l_bp_array \array_set_from_clist:Nn \l_bp_array { 1pt, 2pt, 3pt }
\array_log:N \l_bp_array
\ExplSyntaxOff
\end{document}

然后.log包含:

The sequence \l_bp_array is empty
> .
The sequence \l_bp_array contains the items (without outer braces):
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}.
The sequence \l_bp_array contains the items (without outer braces):
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}
>  {3.14159pt}.
The sequence \l_bp_array contains the items (without outer braces):
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}
>  {0.0pt}.
The sequence \l_bp_array contains the items (without outer braces):
>  {1.0pt}
>  {2.0pt}
>  {3.0pt}.

然后您可以轻松定义该环境:

\documentclass{article}
\usepackage{bparray}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l_myenv_int
\array_new:N \l_myenv_array
\array_set_from_clist:Nn \l_myenv_array { 5pt, 7.35pt }
\NewDocumentEnvironment {myEnv} { }
  { \int_incr:N \l_myenv_int } { }
\NewDocumentCommand \arrayitem { }
  { \array_item:Nn \l_myenv_array { \l_myenv_int } }
\NewDocumentCommand \arrayindex { }
  { \int_use:N \l_myenv_int }
\ExplSyntaxOff
\begin{document}
Array index = \arrayindex{} and array item = \arrayitem\par
\begin{myEnv}
  Array index = \arrayindex{} and array item = \arrayitem\par
  \begin{myEnv}
    Array index = \arrayindex{} and array item = \arrayitem\par
  \end{myEnv}
  Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
Array index = \arrayindex{} and array item = \arrayitem\par
\end{document}

输出为:

在此处输入图片描述


但是看起来您实际上并不需要动态分配。上面的结果可以通过以下方式轻松实现fparray(不同之处在于可能会发生索引越界错误):

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\int_new:N \l_myenv_int
\fparray_new:Nn \l_myenv_fparray { 2 }
\fparray_gset:Nnn \l_myenv_fparray { 1 } { 5pt }
\fparray_gset:Nnn \l_myenv_fparray { 2 } { 7.35pt }
\NewDocumentEnvironment {myEnv} { }
  { \int_incr:N \l_myenv_int } { }
\NewDocumentCommand \arrayitem { }
  { \dim_eval:n { \fparray_item:Nn \l_myenv_fparray { \l_myenv_int } pt } }
\NewDocumentCommand \arrayindex { }
  { \int_use:N \l_myenv_int }
\ExplSyntaxOff
\begin{document}
% Array index = \arrayindex{} and array item = \arrayitem\par % Error
\begin{myEnv}
  Array index = \arrayindex{} and array item = \arrayitem\par
  \begin{myEnv}
    Array index = \arrayindex{} and array item = \arrayitem\par
  \end{myEnv}
  Array index = \arrayindex{} and array item = \arrayitem\par
\end{myEnv}
% Array index = \arrayindex{} and array item = \arrayitem\par % Error
\end{document}

输出:

在此处输入图片描述

相关内容