如何修改 l3seq 或 l3clist 中的单个项目,就像修改其他编程语言中的普通“数组”一样?像这样:a[n] = x
。
\seq_item:Nn
可能会留下一个“右值”,但如何得到一个可以改变的“左值”呢?
答案1
我不建议使用seq
或clist
“变量”来提供类似数组的功能。
列表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
?
可以轻松添加一个测试,使索引指向超出序列当前长度的整数。