如何修改 l3seq/l3clist 中的单个项目

如何修改 l3seq/l3clist 中的单个项目

如何修改 l3seq 或 l3clist 中的单个项目,就像修改其他编程语言中的普通“数组”一样?像这样:a[n] = x

\seq_item:Nn可能会留下一个“右值”,但如何得到一个可以改变的“左值”呢?

答案1

我不建议使用seqclist“变量”来提供类似数组的功能。

列表property非常强大,虽然速度不如 快\seq,但允许通过应用键/值直接更改元素。key此处 是数组元素的编号, 值是数组的单元格值。但是,property列表也可以用作哈希。

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\prop_new:N \g_stonezeng_array_prop

\NewDocumentCommand{\fillarray}{+m}{
  \group_begin:
  \seq_set_from_clist:Nn \l_tmpa_seq {#1}
  \int_zero:N \l_tmpa_int
  \seq_map_inline:Nn \l_tmpa_seq {
    \int_incr:N \l_tmpa_int
    \prop_gput:NVn \g_stonezeng_array_prop {\l_tmpa_int }{##1}
  }
  \group_end:
}

\NewDocumentCommand{\ChangeElement}{m+m}{
  \prop_gput:Nnn \g_stonezeng_array_prop {#1}{ #2}
}

\NewDocumentCommand{\RemoveElement}{m}{
  \prop_gremove:Nn \g_stonezeng_array_prop {#1}
}

\NewDocumentCommand{\showarray}{}{
  \prop_map_inline:Nn  \g_stonezeng_array_prop {
    a[##1]~=##2\par

  }

}
\ExplSyntaxOff

\begin{document}

\fillarray{20,19,18}

\showarray

\ChangeElement{3}{21}


\showarray


\end{document}

在此处输入图片描述

答案2

当设置了一个序列或列表时,它只能通过“弹出”最左边或最右边的项目来修改,这意味着将其移除并将其存储在标记列表变量中; 函数是

\seq_pop_left:NN
\seq_pop_right:NN
\clist_pop_left:NN
\clist_pop_right:NN

及其全局对应部分(用gpop而不是pop);全局变体只会全局删除该项目,但对标记列表变量的分配始终是本地的。

为了修改序列中的项目,您需要重建它。可能的实现如下

\cs_new_protected:Nn \stonezeng_change_seq_item:Nnn
 {% #1 = sequence, #2 = index, #3 = the new item
  \__stonezeng_change_item:NNnn \seq_set_eq:NN #1 { #2 } { #3 }
 }
\cs_new_protected:Nn \stonezeng_gchange_seq_item:Nnn
 {% #1 = sequence, #2 = index, #3 = the new item
  \__stonezeng_change_item:NNnn \seq_gset_eq:NN #1 { #2 } { #3 }
 }

\seq_new:N \l__stone_zeng_temp_seq
\cs_new_protected:Nn \__stone_change_item:NNnn
 {
  \seq_clear:N \l__stone_zeng_temp_seq
  \int_step_inline:nnnn { 1 } { 1 } { \seq_count:N #2 }
   {
    \int_compare:nNnTF { ##1 } = { #3 }
     {
      \seq_put_right:Nn \l__stone_zeng_temp_seq { #4 }
     }
     {
      \seq_put_right:Nn \l__stone_zeng_temp_seq { \seq_item:Nn #2 { ##1 } }
     }
   }
  #1 #2 \l__stone_zeng_temp_seq
 }

全面测试

\documentclass{article}
\usepackage{expl3}

\ExplSyntaxOn

\cs_new_protected:Nn \stonezeng_change_seq_item:Nnn
 {% #1 = sequence, #2 = index, #3 = the new item
  \__stonezeng_change_seq_item:NNnn \seq_set_eq:NN #1 { #2 } { #3 }
 }
\cs_new_protected:Nn \stonezeng_gchange_seq_item:Nnn
 {% #1 = sequence, #2 = index, #3 = the new item
  \__stonezeng_change_seq_item:NNnn \seq_gset_eq:NN #1 { #2 } { #3 }
 }

\seq_new:N \l__stone_zeng_temp_seq
\cs_new_protected:Nn \__stonezeng_change_seq_item:NNnn
 {
  \seq_clear:N \l__stone_zeng_temp_seq
  \int_step_inline:nnnn { 1 } { 1 } { \seq_count:N #2 }
   {
    \int_compare:nNnTF { ##1 } = { #3 }
     {
      \seq_put_right:Nn \l__stone_zeng_temp_seq { #4 }
     }
     {
      \seq_put_right:Nx \l__stone_zeng_temp_seq { \seq_item:Nn #2 { ##1 } }
     }
   }
  #1 #2 \l__stone_zeng_temp_seq
 }

%%% test

\seq_new:N \l_stone_zeng_test_seq
\seq_new:N \g_stone_zeng_test_seq

\seq_set_from_clist:Nn \l_stone_zeng_test_seq { a, b, c, d }

\stonezeng_change_seq_item:Nnn \l_stone_zeng_test_seq { 3 } { z }

\seq_show:N \l_stone_zeng_test_seq

\group_begin:
\seq_gset_from_clist:Nn \g_stone_zeng_test_seq { a, b, c, d }

\stonezeng_gchange_seq_item:Nnn \g_stone_zeng_test_seq { 4 } { u }
\group_end:

\seq_show:N \g_stone_zeng_test_seq

\stop

控制台上的输出:

The sequence \l_stone_zeng_test_seq contains the items (without outer braces):
>  {a}
>  {b}
>  {z}
>  {d}.
<recently read> }

l.41 \seq_show:N \l_stone_zeng_test_seq

? 
The sequence \g_stone_zeng_test_seq contains the items (without outer braces):
>  {a}
>  {b}
>  {c}
>  {u}.
<recently read> }

l.49 \seq_show:N \g_stone_zeng_test_seq

? 

可以轻松添加一个测试,使索引指向超出序列当前长度的整数。

相关内容