第一种可能性

第一种可能性

我想使用 来处理数据结构expl3。此数据结构将按照以下格式从文件读取和写入文件.aux(这是我的提议 - 当然,我愿意接受更好的建议):

\my@load@command{%
  \my@start@key{keyA}%
  \my@additem{item1}%
  \my@additem{item2}%

  (...)

  \my@additem{itemn}%
  \my@stop@key
  \my@start@key{keyB}%
  \my@additem{item1}%
  \my@additem{item2}%

  (...)

  \my@additem{itemn}%
  \my@stop@key

  (...)

  \my@stop@key
}

此代码表示的数据结构是从字符串到字符串列表的映射。换句话说,每个键都是一个唯一的字符串,并映射到一个项目列表,其中每个项目本身都是一个字符串(按照 LaTeX3 的类型str)。我的代码将确保对于给定的键,列表中的所有项目都是唯一的(但它们的顺序很重要,因此这不是“集合语义”)。

我的问题是如何使用当前的 LaTeX3 工具集以“最佳方式”对此进行建模。

第一种可能性

有一个全局属性列表(来自l3prop),其中每个键都映射到一个 〈balanced text〉,该列表使用分隔符(例如\q_nil或逗号)描述关联的项目列表(在后一种情况下,为了一般性,每个 〈balanced text〉 都可以是这种形式,并且我认为{〈item〉},{〈item〉},...,{〈item〉}可以将其变成seq使用)。\seq_set_from_clist:Nn

这意味着当需要为给定的键添加一个项目时:

  • \seq_set_split:Nnn首先,我们从全局属性列表中检索相应的值作为 〈balanced text〉 标记列表,然后使用或将其转换为序列\seq_set_from_clist:Nn

  • 如果该项目尚不存在,我们就将其附加到序列中;

  • 最后,如果这确实是一个新项目,我们将结果项目列表写入全局属性列表(作为与我们正在处理的键关联的值)。

这些操作可能有点慢,但是这种方法似乎不会浪费寄存器等潜在的稀缺资源。

第二种可能性

有一个序列或逗号列表来存储迄今为止看到的键列表,并且每当我们向该列表添加新键时,使用类似以下内容创建关联序列:

\seq_new:c { g__my_list_of_items_for_ #1 }

其中#1代表键名称。

这样,操作给定键的项目列表就很容易了,但是我们创建每个键一个序列变量文档中可以看到。例如,给定文档中可能会有几千个键,理论上,多个包可能正在执行相同的操作。这是对 TeX 资源的正确使用吗?例如,如果每个seq变量都存储在 TeX 寄存器中,1在我看来,考虑到寄存器的数量有限(这可能取决于引擎和用于此目的的寄存器的精确类型,但如果是这种情况,我认为我更喜欢一种仅受“软参数”限制的方法,例如TeX 实现的number of stringspool size和)。hash size

底线:第二种方法有一些优点,但由于不知道seq变量在 LaTeX3 中是如何实现的,所以我不知道它是否能很好地扩展。


脚注

  1. 我不知道是否是这样。

答案1

这是原型。序列实际上是宏,因此它们只会影响字符串和哈希表的内存。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\keyadd}{mm}
 {
  \seq_if_exist:cF { g_my_items_for_#1_seq }
   {
    \seq_gput_right:Nn \g_my_keys_seq { #1 } % the list of keys
    \seq_new:c { g_my_items_for_#1_seq }
   }
  \seq_gput_right:cn { g_my_items_for_#1_seq } { #2 }
 }

\seq_new:N \g_my_keys_seq

\cs_generate_variant:Nn \seq_set_split:Nnn { c }

\cs_new_protected:cpn { my@define@key } #1 #2
 {
  \seq_gput_right:Nn \g_my_keys_seq { #1 } % the list of keys
  \__my_key_new:n { #1 }
  \seq_set_split:cnn { g_my_items_for_#1_seq } { } { #2 }
 }

\cs_new_protected:Nn \__my_key_new:n
 {
  \seq_new:c { g_my_items_for_#1_seq }
 }

\cs_new:Nn \__my_write_key:n
 {
  \token_to_str:N \my@define@key { #1 }
   {
    ^^J
    \seq_map_function:cN { g_my_items_for_#1_seq } \__my_write_item:n
   }
  ^^J
 }
\cs_new:Nn \__my_write_item:n { {#1} ^^J }

\AtEndDocument
 {
  \cs_set_eq:NN \__my_key_new:n \use_none:n
  \iow_now:cx { @auxout } { \seq_map_function:NN \g_my_keys_seq \__my_write_key:n }
 }

\ExplSyntaxOff

\begin{document}

Some text

\keyadd{keyA}{item1}
\keyadd{keyA}{item2}
\keyadd{keyA}{item3}
\keyadd{keyA}{item4}
\keyadd{keyA}{item5}
\keyadd{keyA}{item6}
\keyadd{keyA}{item7}

\keyadd{keyB}{item1}
\keyadd{keyB}{item2}
\keyadd{keyB}{item3}
\keyadd{keyB}{item4}

\end{document}

.aux文件将包含

\relax 
\my@define@key{keyA}{
{item1}
{item2}
{item3}
{item4}
{item5}
{item6}
{item7}
}
\my@define@key{keyB}{
{item1}
{item2}
{item3}
{item4}
}

相关内容