
Tengo un documento compuesto por tres tablas grandes de varias páginas, todas las cuales tienen enlaces a elementos en una lista de figuras al final. Al generar etiquetas md5 cuando genero el látex para las tablas, puedo incluir enlaces a las tablas de origen. Sin embargo, varios elementos vinculados a una figura a menudo estarán en la misma página, lo que generará 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.
En el documento generado, cada uno de esos números de página es un enlace a la línea de la tabla que hace referencia a esa figura.
Me gustaría lograr dos cosas:
- Eliminar duplicados, de modo que solo haya una referencia a la primera entrada de la tabla en una página determinada.
- (opcional) Ordenar la lista por número de página
He visto la pregunta sobre la deduplicación de listas.aquí, pero soy nuevo en látex y ni siquiera puedo hacer que mi ejemplo de trabajo mínimo, publicado a continuación, funcione realmente:
\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}
Cuando intento ejecutar eso, una simple modificación del ejemplo del enlace, obtengo alrededor de una docena de errores para cada una de las \renewduplicates
líneas, quejándome de faltantes \endcsname
, extra \endcsname
y extra \else
. No tengo idea de cómo depurar eso.
Respuesta1
Estás usando \edef
y \pageref
no se puede usar en este contexto, ni puede aparecer en\csname...\endcsname
Evitar la expansión completa funcionará, junto con encadenar la expansión de primer nivel de \next
when in \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
Sin embargo, hay una manera más ingeniosa:
\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}
Aquí está el resultado en mi 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
?
Ordenar es imposible en este nivel.
Si desea eliminar los duplicados del número de página, en lugar de los \pageref{...}
duplicados, necesita la versión ampliable \pageref
proporcionada por refcount
. Mostraré el código en las dos versiones. Primero 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}
Luego la versión “clásica”:
\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 versiones definen \blist
y redefinen \alist
para contener "1,2".
Una versión que utiliza la lista creada para imprimir hipervínculos a las 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}