
У меня есть документ, состоящий из трех больших многостраничных таблиц, все из которых имеют ссылки на элементы в списке рисунков в конце. Генерируя метки md5 при генерации latex для таблиц, я могу включить ссылки обратно на исходные таблицы. Однако несколько элементов, ссылающихся на рисунок, часто будут находиться на одной странице, что приведет к таким чудовищностям:
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.
В сгенерированном документе каждый из этих номеров страниц является ссылкой на строку в таблице, которая ссылается на этот рисунок.
Я хотел бы добиться двух вещей:
- Устранить дубликаты, чтобы на данной странице была только ссылка на первую запись таблицы.
- (необязательно) Сортировать список по номеру страницы
Я видел вопрос о дедупликации списказдесь, но я новичок в латексе и даже мой минимальный рабочий пример, размещенный ниже, не может работать:
\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
, жалуясь на missing \endcsname
, extra \endcsname
, и extra \else
. Я понятия не имею, как это отладить.
решение1
Вы используете \edef
и \pageref
не можете использовать его в этом контексте, а также не можете появляться в\csname...\endcsname
Избежание полного расширения будет работать вместе с преобразованием расширения первого уровня в строку, \next
когда в \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{...}
дубликаты, вам нужна расширяемая версия, \pageref
предоставленная refcount
. Я покажу код в двух версиях. Первая 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}
А вот «классическая» версия:
\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}