Como desduplicar e classificar uma lista de \pagerefs?

Como desduplicar e classificar uma lista de \pagerefs?

Tenho um documento composto por três tabelas grandes de várias páginas, todas com links para itens em uma lista de figuras no final. Ao gerar rótulos md5 ao gerar o látex para as tabelas, posso incluir links para as tabelas de origem. No entanto, vários itens vinculados a uma figura geralmente estarão na mesma página, levando a monstruosidades como esta:

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.

No documento gerado, cada um desses números de página é um link para a linha da tabela que faz referência a essa figura.

Eu gostaria de realizar duas coisas:

  1. Elimine duplicatas, para que haja apenas uma referência à primeira entrada da tabela em uma determinada página
  2. (opcional) Classifique a lista pelo número da página

Eu vi a pergunta sobre desduplicação de listaaqui, mas sou novo no látex e não consigo nem fazer com que meu exemplo mínimo de trabalho, postado abaixo, realmente funcione:

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

Quando tento executar isso, uma simples modificação do exemplo do link, recebo cerca de uma dúzia de erros para cada uma das \renewduplicateslinhas, reclamando de missing \endcsname, extra \endcsnamee extra \else. Não tenho ideia de como depurar isso.

Responder1

Você está usando \edefe \pagerefnão pode ser usado neste contexto, nem pode aparecer em\csname...\endcsname

Evitar a expansão total funcionará, juntamente com restringir a expansão de primeiro nível de \nextquando estiver no \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

No entanto, há uma maneira mais inteligente:

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

Aqui está a saída no meu terminal:

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

? 

A classificação é impossível neste nível.


Se quiser remover as duplicatas do número de página, em vez das \pageref{...}duplicatas, você precisará da versão expansível \pagereffornecida por refcount. Vou mostrar o código nas duas versões. Primeiro expl3:

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

Depois a versão “clássica”:

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

Ambas as versões definem \bliste redefinem \alistpara conter “1,2”.


Uma versão que utiliza a lista construída para imprimir hiperlinks para as páginas.

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

informação relacionada