在这个答案我们学会了如何删除n来自逗号分隔列表的第个元素。
如何通过其从列表中删除元素价值,而不是其位置? 例如:如果我的全局变量\citylist
当前的值为derby,leicester,nottingham
,那么执行后\removecity{leicester}
我希望它具有 的值derby,nottingham
。
我已经有一个\addcity
宏(我通过改编David Carlisle 的宏):
\newcommand\addcity[1]{%
\ifx\citylist\@empty\else\g@addto@macro\citylist{,}\fi
\g@addto@macro\citylist{#1}
}
答案1
在简单的情况下,你可以使用 LaTeX 的\@removeelement
:
\documentclass{article}
\newcommand*{\citylist}{derby,leicester,nottingham}
\makeatletter
\@expandtwoargs\@removeelement{leicester}\citylist\citylist
\makeatother
\typeout{\citylist}
\begin{document}
\end{document}
结果:
derby,nottingham
简单意味着列表是规范化的,逗号周围没有可选的空格。列表元素不包含逗号和宏。
带有包装的变体kvsetkeys
:
\documentclass{article}
\usepackage{kvsetkeys}
\makeatletter
\newcommand*{\addcity}[1]{%
\ifx\citylist\@empty\else\g@addto@macro\citylist{,}\fi
\g@addto@macro\citylist{#1}
}
\newcommand*{\removecity}[1]{%
\def\unwanted@city{#1}%
\edef\citylist{\expandafter}%
\expandafter\comma@parse\expandafter{\citylist}\@removecity
}
\newcommand*{\@removecity}[1]{%
\def\param@city{#1}%
\ifx\param@city\unwanted@city
\else
\addcity{#1}%
\fi
}
\makeatother
\newcommand*{\citylist}{derby,leicester,nottingham}
\removecity{leicester}
\typeout{\citylist}
\begin{document}
\end{document}
那么空间就不会干扰,例如:
\newcommand*{\citylist}{derby, leicester, nottingham}
城市名称可能包含命令和脆弱的宏,它们不会被扩展。
根据以下定义\addcity
,城市名称甚至可能包含逗号:
\newcommand*{\addcity}[1]{%
\ifx\citylist\@empty\else\g@addto@macro\citylist{,}\fi
\g@addto@macro\citylist{{#1}}
}
列表示例:
{derby},{leicester},{berlin, west},{berlin, east}
答案2
这expl3
suite 可以通过多种方式管理逗号分隔的列表。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\createlist}{mm}
{
\clist_new:c { g_wickerson_data_#1_clist }
\clist_gset:cn { g_wickerson_data_#1_clist } { #2 }
}
\NewDocumentCommand{\addtolist}{mm}
{
\clist_gput_right:cn { g_wickerson_data_#1_clist } { #2 }
}
\NewDocumentCommand{\removefromlist}{mm}
{
\clist_gremove_all:cn { g_wickerson_data_#1_clist } { #2 }
}
\NewDocumentCommand{\purgelist}{m}
{
\clist_gremove_duplicates:c { g_wickerson_data_#1_clist }
}
\NewDocumentCommand{\printlist}{m}
{
\clist_use:cnnn { g_wickerson_data_#1_clist } { ,~ } { ,~ } { ,~ }
}
\cs_generate_variant:Nn \clist_use:Nnnn { c }
\ExplSyntaxOff
%%% working with a specific list without needing two args
\newcommand{\addcity}[1]{\addtolist{city}{#1}}
\newcommand{\removecity}[1]{\removefromlist{city}{#1}}
\newcommand{\printcity}{\printlist{city}}
\createlist{city}{derby,leicester} % initialization
\begin{document}
\addcity{nottingham}
Cities: \printcity
\bigskip
\removecity{leicester}
Cities: \printcity
\end{document}
然而,逗号列表并不是最高效的数据类型:序列更佳。而且内部实现也不必担心。
用以下方法可以更快实现同样的效果
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\createlist}{mm}
{
\seq_new:c { g_wickerson_data_#1_seq }
\seq_gset_from_clist:cn { g_wickerson_data_#1_seq } { #2 }
}
\NewDocumentCommand{\addtolist}{mm}
{
\seq_gput_right:cn { g_wickerson_data_#1_seq } { #2 }
}
\NewDocumentCommand{\removefromlist}{mm}
{
\seq_gremove_all:cn { g_wickerson_data_#1_seq } { #2 }
}
\NewDocumentCommand{\purgelist}{m}
{
\seq_gremove_duplicates:c { g_wickerson_data_#1_seq }
}
\NewDocumentCommand{\printlist}{m}
{
\seq_use:cnnn { g_wickerson_data_#1_seq } { ,~ } { ,~ } { ,~ }
}
\cs_generate_variant:Nn \seq_use:Nnnn { c }
\ExplSyntaxOff
%%% working with a specific list without needing two args
\newcommand{\addcity}[1]{\addtolist{city}{#1}}
\newcommand{\removecity}[1]{\removefromlist{city}{#1}}
\newcommand{\printcity}{\printlist{city}}
\createlist{city}{derby,leicester} % initialize
\begin{document}
\addcity{nottingham}
Cities: \printcity
\bigskip
\removecity{leicester}
Cities: \printcity
\end{document}