使用索引引用列表宏中的元素

使用索引引用列表宏中的元素

这是我想要实现的一个最小示例:

我已经定义了一个列表,例如:

\def\listA{1/a/A,   2/b/B,  3/c/C}

我现在可以使用以下方法成功循环遍历此列表

\foreach \x/\i/\j in \listA

不过我希望能够使用索引号从该列表中挑选项目。

例如,我希望能够做这样的事情:

ASSIGN \x/\i/\j listA[1]
\x   [this would print 1]
\i   [this would print a]
\j   [this would print A]

ASSIGN \x/\i/\j listA[2]
\x   [this would print 2]
\i   [this would print b]
\j   [this would print B]

可以这样做吗?谢谢!

答案1

由于您正在使用pgffor,这里有一些东西可以做您想要的事情:

\documentclass{article}
\usepackage{pgffor}
\begin{document}
\def\listA{1/a/A,2/b/B,3/c/C}
\newcommand{\Assign}[1]{\foreach [count=\nn] \myx/\myi/\myj in \listA
{\ifnum\nn=#1 
\xdef\x{\myx}
\xdef\i{\myi}
\xdef\j{\myj}
\fi}
}
\Assign{1}
\x
\Assign{2}
\i
\end{document}

1 b

然而,我个人不会这么做。

答案2

这是一项提议,没有\x等等,因为分组似乎不可能,以避免(像\foreach那样)破坏现有命令。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\definelist}{mm}
 {
  \clist_clear_new:c { l_ijm_list_#1_clist }
  \clist_set:cn { l_ijm_list_#1_clist } { #2 }
 }

\NewDocumentCommand{\assign}{mmm}
 {% #1 = list name, #2 = template, #3 = item number
  \ijm_list_assign:nnn { #1 } { #2 } { #3 }
 }

\NewExpandableDocumentCommand{\get}{m}
 {
  \prop_item:Nn \l__ijm_list_assign_prop { #1 }
 }

\seq_new:N \l__ijm_list_template_seq
\seq_new:N \l__ijm_list_item_seq
\prop_new:N \l__ijm_list_assign_prop
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }

\cs_new_protected:Nn \ijm_list_assign:nnn
 {
  \seq_set_split:Nnn \l__ijm_list_template_seq { / } { #2 }
  \seq_set_split:Nnx \l__ijm_list_item_seq { / }
   {
    \clist_item:cn { l_ijm_list_#1_clist } { #3 }
   }
  \prop_clear:N \l__ijm_list_assign_prop
  \seq_mapthread_function:NNN
    \l__ijm_list_template_seq
    \l__ijm_list_item_seq
    \__ijm_list_assign:nn
 }

\cs_new_protected:Nn \__ijm_list_assign:nn
 {
  \prop_put:Nnn \l__ijm_list_assign_prop { #1 } { #2 }
 }

\ExplSyntaxOff

\begin{document}

\definelist{listA}{1/a/A, 2/b/B, 3/c/C}

\assign{listA}{x/y/z}{1}

\get{x}\par
\get{y}\par
\get{z}\par

\assign{listA}{x/y/z}{2}

\get{x}\par
\get{y}\par
\get{z}\par

\end{document}

您定义一个列表,然后可以将\assign字母(或更一般地,字符串)添加到项目中,请参见示例。项目通过 生成\get{<letter>}

在此处输入图片描述

另一种方法。列表的定义与以前相同(但您可以更改分隔符)。您无需分配符号名称,而是可以以“矩阵”形式访问项目,即

\get{<item number>}[<subitem number>]{<list name>}

第二个参数是可选的;如果省略,则返回整个项目。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\definelist}{O{/}mm}
 {% #1 = divider (optional), #2 = name, #3 = items
  \seq_clear_new:c { l_ijm_list_#2_seq }
  \seq_set_from_clist:Nn \l__ijm_list_tempa_seq { #3 }
  \seq_map_inline:Nn \l__ijm_list_tempa_seq
   {
    \seq_set_split:Nnn \l__ijm_list_tempb_seq { #1 } { ##1 }
    \tl_clear:N \l__ijm_list_tempa_tl
    \seq_map_inline:Nn \l__ijm_list_tempb_seq
     {
      \tl_put_right:Nn \l__ijm_list_tempa_tl { {####1} }
     }
    \seq_put_right:cV { l_ijm_list_#2_seq } \l__ijm_list_tempa_tl
   }
 }

\NewExpandableDocumentCommand{\get}{mom}
 {
  \IfNoValueTF { #2 }
   {
    \seq_item:cn { l_ijm_list_#3_seq } { #1 }
   }
   {
    \tl_item:fn { \seq_item:cn { l_ijm_list_#3_seq } { #1 } } { #2 }
   } 
 }

\seq_new:N \l__ijm_list_tempa_seq
\seq_new:N \l__ijm_list_tempb_seq
\tl_new:N \l__ijm_list_tempa_tl
\cs_generate_variant:Nn \tl_item:nn { f }

\ExplSyntaxOff

\begin{document}

\definelist{listA}{1/a/A, 2/b/B, 3/c/C}

\get{1}[1]{listA}\par
\get{1}[2]{listA}\par
\get{1}[3]{listA}\par
\get{2}[1]{listA}\par
\get{2}[2]{listA}\par
\get{2}[3]{listA}\par
\get{3}{listA}

\end{document}

在此处输入图片描述

答案3

\documentclass{article}
\usepackage{xinttools}

\newcommand{\Assign}{}% check macro name is free (if not LaTeX shall complain)

\makeatletter
\def\Assign #1#2/#3#4/#5#6[#7]{%
    \oodef\Assign@tmp
       {\xintNthElt{#7}{\xintCSVtoList{\csname \xintZapSpaces{#6}\endcsname}}}%
    \expandafter\Assign@aux\Assign@tmp /#1/#3/#5/%
}
\def\Assign@aux #1/#2/#3/#4/#5/#6/{%
    \oodef#4{\xintZapSpaces{#1}}% remove leading and trailing spaces
                                % from item. Maybe not desired?
                                % see how 2/ b / B is handled
    \oodef#5{\xintZapSpaces{#2}}%
    \oodef#6{\xintZapSpaces{#3}}%
}%
\makeatother

\def\listA{1/a/A,    2/ b / B ,  3/c/C}

\begin{document}

\ttfamily

\Assign \x/\i/\j listA[1]

\string\x\ is \meaning\x+++

\string\i\ is \meaning\i+++

\string\j\ is \meaning\j+++

\Assign \X/\I/\J listA[2]

\string\X\ is \meaning\X+++

\string\I\ is \meaning\I+++

\string\J\ is \meaning\J+++
\end{document}

生产

在此处输入图片描述

相关内容