从逗号分隔列表中删除元素

从逗号分隔列表中删除元素

这个答案我们学会了如何删除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

expl3suite 可以通过多种方式管理逗号分隔的列表。

\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}

相关内容