如何对 \pagerefs 列表进行重复数据删除和排序?

如何对 \pagerefs 列表进行重复数据删除和排序?

我有一个由三个大型多页表格组成的文档,所有这些表格都包含指向末尾图表列表中项目的链接。通过在为表格生成 latex 时生成 md5 标签,我可以将链接返回到原始表格。但是,链接到一个图表的多个项目通常会在同一页上,从而导致如下错误:

Figure 31 - This figure was referenced on pages 4, 4, 4, 14, 17, 17, 27, 30, 30, 6, 6, 6, 6, 6, 6, 8, 8, 8, 19, 19, 20, 20, 21, 21, 21, 21, 21, 32, 32, 33, 33, 34, 34, 34 34, and 34.

在生成的文档中,每个页码都是指向表格中引用该图的行的一个链接。

我想完成两件事:

  1. 消除重复项,以便仅引用给定页面上的第一个表格条目
  2. (可选)按页码对列表进行排序

我见过列表去重问题这里但是我对 Latex 还不熟悉,我甚至无法让下面发布的最小工作示例真正发挥作用:

\documentclass[letterpaper,11pt,openany,oneside]{book}

\makeatletter
\def\removeduplicates#1#2{\begingroup
  \let\@tempa#1%
  \def\@tempb{}%
  \@for\next:=\@tempa\do
    {\@ifundefined{lstel@\next}
      {\edef\@tempb{\@tempb,\next}
       \expandafter\let\csname lstel@\next\endcsname\@empty}
      {}%
    }%
  \edef\x{\endgroup\def\noexpand#2{\@tempb}}\x
  \expandafter\strip@comma#2\@nil#2}
\def\strip@comma,#1\@nil#2{\def#2{#1}}
\makeatother

\begin{document}
% some labels on page 1
\section{John} \label{john}
john doe
\section{Mary} \label{mary}
mary sue

%move to page 2
\clearpage
\section{George} \label{george}
george weasley
\section{Australia} \label{australia}
crocodile dundee

%new page, where the references are
\clearpage
\section{References}

\def\alist{\pageref{john},\pageref{mary},\pageref{george},\pageref{australia},\pageref{australia},\pageref{john}}   
\removeduplicates\alist\blist

\show\blist
\show\alist

\removeduplicates\alist\alist
\show\alist

\end{document}

当我尝试运行该示例时,对链接中的示例进行了简单的修改,我每行都会收到大约十几个错误\renewduplicates,抱怨缺少\endcsname、额外\endcsname和额外\else。 我不知道如何进行调试。

答案1

您正在使用\edef,并且\pageref不能在此上下文中使用,也不能出现在\csname...\endcsname

避免完全扩展将会起作用,同时将\nextwhen的第一级扩展字符串化\csname...\endcsname

\providecommand{\expandonce}{\unexpanded\expandafter}
\makeatletter
\def\removeduplicates#1#2{\begingroup
  \let\@tempa#1%
  \def\@tempb{}%
  \@for\next:=\@tempa\do
    {\@ifundefined{lstel@\detokenize\expandafter{\next}}
      {\edef\@tempb{\expandonce{\@tempb},\expandonce{\next}}
       \expandafter\let\csname lstel@\detokenize\expandafter{\next}\endcsname\@empty}
      {}%
    }%
  \edef\x{\endgroup\def\noexpand#2{\expandonce{\@tempb}}}\x
  \expandafter\strip@comma#2\@nil#2}
\def\strip@comma,#1\@nil#2{\def#2{#1}}
\makeatother

然而,有一个更巧妙的方法:

\documentclass[letterpaper,11pt,openany,oneside]{book}

\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\removeduplicates}{mm}
 {
  \seq_set_split:NnV \l_tmpa_seq { , } #1
  \seq_remove_duplicates:N \l_tmpa_seq
  \tl_set:Nx #2 { \seq_use:Nn \l_tmpa_seq { , } }
 }
\ExplSyntaxOff

\begin{document}
% some labels on page 1
\section{John} \label{john}
john doe
\section{Mary} \label{mary}
mary sue

%move to page 2
\clearpage
\section{George} \label{george}
george weasley
\section{Australia} \label{australia}
crocodile dundee

%new page, where the references are
\clearpage
\section{References}

\def\alist{\pageref{john},\pageref{mary},\pageref{george},%
  \pageref{australia},\pageref{australia},\pageref{john}}   

\removeduplicates\alist\blist

\show\blist
\show\alist

\removeduplicates\alist\alist
\show\alist

\end{document}

这是我的终端上的输出:

> \blist=macro:
->\pageref {john},\pageref {mary},\pageref {george},\pageref {australia}.
l.37 \show\blist

? 
> \alist=macro:
->\pageref {john},\pageref {mary},\pageref {george},\pageref {australia},\pager
ef {australia},\pageref {john}.
l.38 \show\alist

? 
> \alist=macro:
->\pageref {john},\pageref {mary},\pageref {george},\pageref {australia}.
l.41 \show\alist

? 

在这个级别上不可能进行排序。


如果您想要删除页码重复项,而不是重复项,则需要提供的\pageref{...}可扩展版本。我将展示两个版本的代码。首先:\pagerefrefcountexpl3

\documentclass[letterpaper,11pt,openany,oneside]{book}
\usepackage{refcount}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\removeduplicates}{mm}
 {
  \clist_set:Nx \l_tmpa_clist { #1 }
  \clist_remove_duplicates:N \l_tmpa_clist
  \tl_set:NV #2 \l_tmpa_clist
 }
\ExplSyntaxOff

\begin{document}
% some labels on page 1
\section{John} \label{john}
john doe
\section{Mary} \label{mary}
mary sue

%move to page 2
\clearpage
\section{George} \label{george}
george weasley
\section{Australia} \label{australia}
crocodile dundee

%new page, where the references are
\clearpage
\section{References}

\def\alist{\getpagerefnumber{john},\getpagerefnumber{mary},\getpagerefnumber{george},%
  \getpagerefnumber{australia},\getpagerefnumber{australia},\getpagerefnumber{john}}   

\removeduplicates\alist\blist

\show\blist
\show\alist

\removeduplicates\alist\alist
\show\alist

\alist

\blist

\end{document}

接下来是“经典”版本:

\documentclass[letterpaper,11pt,openany,oneside]{book}
\usepackage{refcount}

\makeatletter
\def\removeduplicates#1#2{\begingroup
  \let\@tempa#1%
  \def\@tempb{}%
  \@for\next:=\@tempa\do
    {\@ifundefined{lstel@\next}
      {\edef\@tempb{\@tempb,\next}%
       \expandafter\let\csname lstel@\next\endcsname\@empty}
      {}%
    }%
  \edef\x{\endgroup\def\noexpand#2{\@tempb}}\x
  \expandafter\strip@comma#2\@nil#2}
\def\strip@comma,#1\@nil#2{\def#2{#1}}
\makeatother

\begin{document}
% some labels on page 1
\section{John} \label{john}
john doe
\section{Mary} \label{mary}
mary sue

%move to page 2
\clearpage
\section{George} \label{george}
george weasley
\section{Australia} \label{australia}
crocodile dundee

%new page, where the references are
\clearpage
\section{References}

\def\alist{\getpagerefnumber{john},\getpagerefnumber{mary},\getpagerefnumber{george},\getpagerefnumber{australia},\getpagerefnumber{australia},\getpagerefnumber{john}}   
\removeduplicates\alist\blist

\show\blist
\show\alist

\removeduplicates\alist\alist
\show\alist

\blist

\alist

\end{document}

两个版本都定义\blist并重新定义\alist为包含“1,2”。


使用构建列表打印页面超链接的版本。

\documentclass[letterpaper,11pt,openany,oneside]{book}
\usepackage{refcount}
\usepackage{xparse}
\usepackage{hyperref}

\ExplSyntaxOn
\NewDocumentCommand{\createlinks}{m}
 {
  \seq_set_split:Nnx \l_tmpa_seq { , } { #1 }
  \seq_remove_duplicates:N \l_tmpa_seq
  \seq_clear:N \l_tmpb_seq
  \seq_map_inline:Nn \l_tmpa_seq
   {
    \seq_put_right:Nn \l_tmpb_seq { \hyperlink { page.##1 } { ##1 } }
   }
  \seq_use:Nn \l_tmpb_seq { ,~ }
 }
\cs_generate_variant:Nn \seq_set_split:Nnn { Nnx }
\ExplSyntaxOff

\begin{document}
% some labels on page 1
\section{John} \label{john}
john doe
\section{Mary} \label{mary}
mary sue

%move to page 2
\clearpage
\section{George} \label{george}
george weasley
\section{Australia} \label{australia}
crocodile dundee

%new page, where the references are
\clearpage
\section{References}

\def\alist{\getpagerefnumber{john},\getpagerefnumber{mary},\getpagerefnumber{george},%
  \getpagerefnumber{australia},\getpagerefnumber{australia},\getpagerefnumber{john}}   

\createlinks\alist

\end{document}

相关内容