\pagerefs のリストを重複排除して並べ替えるにはどうすればよいでしょうか?

\pagerefs のリストを重複排除して並べ替えるにはどうすればよいでしょうか?

3 つの大きな複数ページの表で構成された文書があり、そのすべてに、末尾の図表リスト内の項目へのリンクがあります。表の 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.

生成されたドキュメントでは、各ページ番号は、その図を参照した表の行へのリンクになります。

私は次の 2 つのことを達成したいと考えています。

  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}

リンクからの例を少し変更して実行しようとすると、各行で 、 、 が不足しているというエラーが 12 個ほど表示されます。これ\renewduplicatesをデバッグする方法がわかりません。\endcsname\endcsname\else

答え1

\edefと は、この文脈では使用\pagerefできず、また、\csname...\endcsname

\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

しかし、もっと巧妙な方法があります:

\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{...}拡張可能なバージョンが必要です。 2 つのバージョンのコードを示します。まず:\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}

どちらのバージョンも、「1,2」を含むように定義\blistおよび再定義されています。\alist


作成されたリストを使用してページへのハイパーリンクを印刷するバージョン。

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

関連情報