我有一个(可能)很长的属性列表,values
目前,它们只是标记列表。现在,我想实现一些键可能有多个值。我将把这些多个值存储在中clists
。
因此,对于每个键,我必须测试其值是clist
还是只是一个标记列表。键可能只有一个值的情况可以看作 的一个特殊情况clist
,其中只能在列表中插入一个值。
我请求建议,哪种方法更容易编程:
values
可以是标记列表或clist
s? 或values
所有都是clist
s,但其中一些只能有一个元素?
( key
, value
) 对通常只设置一次,而 将value
被检索几次(其中一些会检索几次,但我估计不会超过五次)。我预计这两种方法的运行时间不会有很大差异。我不确定内存效率是否会成为“全部方法”的问题clist
。
编辑
egreg's
answwr 很棒(像往常一样)。但我没有完整解释这个问题。第一次设置(key
,value
)对时,我没有列表的所有元素(如果它是列表)。所以,我必须:
- 检索
value
- 检查它是否是一个列表,
- 在列表中插入新值
多次,直到列表类型keys
填满。如果我将所有值定义为clists
。我可以跳过步骤 2。但是,当检索它们时,我想我必须检查是否是key
列表。
问题归结为跳过第 2 步是否会使编程变得更容易。
(经过更深入的思考,它可能同样简单/复杂,因为它只是将更难的部分转移到设置或检索values
)
答案1
\prop_put:Nnn
它对你存储的数据不做任何解释,也就是说它不理解这些数据;它就像\tl_set:Nn
在这方面它很像,所以在某种意义上,属性列表(清单)是标记列表的集合(tl) 按名称进行索引。
这可以是列表? 是的,为什么不?
您可以照常存储价值
\prop_put:Nnn \l_textnik_test_prop { a } { 1,2,3,4 }
然后通过将其分配给tl多变的:
\cs_new_protected:Nn \textnik_prop_get_clist:NnN
{
\prop_get:NnN #1 {#2} \l__textnik_prop_get_clist_tl
\clist_set:NV #3 \l__textnik_prop_get_clist_tl
}
以便
\textnik_prop_get_clist:NnN \l_textnik_test_prop { a } \l_textnik_test_clist
效果与
\clist_set:Nn \l_textnik_test_clist { 1,2,3,4 }
如果你想提取值作为tl, 使用\clist_get:NnN
。
这是一个不同的实现:每个属性引用一个clist
。
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
% Define a new data type pcl, only local settings.
% Add variants as needed and support for global setting.
\cs_new_eq:NN \textnik_pcl_new:N \prop_new:N
\cs_new_eq:NN \textnik_pcl_clear_new:N \prop_clear_new:N
\cs_new_eq:NN \textnik_pcl_clear:N \prop_clear:N
\cs_new_eq:NN \textnik_pcl_set_eq:NN \prop_set_eq:NN
\cs_new_eq:NN \textnik_pcl_remove:NN \prop_remove:NN
% a global counter
\int_new:N \g__textnik_pcl_serial_int
\cs_new_protected:Nn \__textnik_pcl_check:Nn
{
\prop_if_in:NnF #1 { #2 }
{% the property doesn't already exist
\int_gincr:N \g__textnik_pcl_serial_int
\prop_put:Nnx #1 { #2 } { \int_to_arabic:n { \g__textnik_pcl_serial_int } }
\clist_new:c { l__textnik_pcl_ \int_to_arabic:n { \g__textnik_pcl_serial_int } _clist }
}
}
% adding items to a pcl
\cs_new_protected:Nn \textnik_pcl_put:Nnn
{
\__textnik_pcl_check:Nn #1 { #2 }
\clist_set:cn { l__textnik_pcl_ \prop_item:Nn #1 { #2 } _clist } { #3 }
}
\cs_new_protected:Nn \textnik_pcl_put_left:Nnn
{
\__textnik_pcl_check:Nn #1 { #2 }
\clist_put_left:cn { l__textnik_pcl_ \prop_item:Nn #1 { #2 } _clist } { #3 }
}
\cs_new_protected:Nn \textnik_pcl_put_right:Nnn
{
\__textnik_pcl_check:Nn #1 { #2 }
\clist_put_right:cn { l__textnik_pcl_ \prop_item:Nn #1 { #2 } _clist } { #3 }
}
% retrieving items from a pcl
\cs_new_protected:Nn \textnik_pcl_get:NnN
{
\clist_set_eq:Nc #3 { l__textnik_pcl_ \prop_item:Nn #1 { #2 } _clist }
}
% showing a pcl
\cs_new_protected:Nn \textnik_pcl_show:N
{
\prop_map_function:NN #1 \__textnik_pcl_show:nn
}
\cs_new_protected:Nn \__textnik_pcl_show:nn
{
\clist_show:c { l__textnik_pcl_ #2 _clist }
}
%%%% Test
\textnik_pcl_new:N \l_textnik_test_pcl
\textnik_pcl_put:Nnn \l_textnik_test_pcl { A } { A1,A2,A3 }
\textnik_pcl_put_right:Nnn \l_textnik_test_pcl { A } { A4,A5 }
\textnik_pcl_put_left:Nnn \l_textnik_test_pcl { A } { A0 }
\textnik_pcl_put:Nnn \l_textnik_test_pcl { B } { B1,B2,B3 }
\textnik_pcl_put_right:Nnn \l_textnik_test_pcl { B } { B4,B5 }
\textnik_pcl_put_left:Nnn \l_textnik_test_pcl { B } { B0 }
\clist_new:N \l_textnik_test_clist
\textnik_pcl_get:NnN \l_textnik_test_pcl {A} \l_textnik_test_clist
\clist_show:N \l_textnik_test_clist
\textnik_pcl_get:NnN \l_textnik_test_pcl {B} \l_textnik_test_clist
\clist_show:N \l_textnik_test_clist
%\textnik_pcl_show:N \l_textnik_test_pcl
Apcl
实际上是 a prop
,但存储的属性只是引用clist
s 数组的数字。
输出为
The comma list \l_textnik_test_clist contains the items (without outer
braces):
> {A0}
> {A1}
> {A2}
> {A3}
> {A4}
> {A5}.
<recently read> }
l.71 \clist_show:N \l_textnik_test_clist
?
The comma list \l_textnik_test_clist contains the items (without outer
braces):
> {B0}
> {B1}
> {B2}
> {B3}
> {B4}
> {B5}.
<recently read> }
l.73 \clist_show:N \l_textnik_test_clist