[Tex/LaTex] List of Figures sorted by Figure number

floatsnumberingpage-numberingsortingtable of contents

I am using

\usepackage{imakeidx}  
\usepackage{hyperref}  

and the command \listoffigures to get the list of figures. Some figures are double-column, some are single-column, and LaTeX does not always place them consecutively.The figures are ordered by page as usual in the list of figures.

However, I would prefer to have the list sorted by Figure number rather than page number, and with the number of figures I am using it would be impractical to change the numbers of any of the figures.

This is a view of the first two pages of the List of Figures:

enter image description here

Note the incorrect figure number order when sorted by page (page 28).

Can this be changed? How?

Best Answer

Of course, David Carlisle has already mentioned in a comment the correct solution, which is to use the fixltx2e package or a new enough LaTeX kernel (now fixltx2e changes are applied by default). Among other goodies, this will ensure that figures appear in the same order in the output as you specified them in the input.

If, however, you like how LaTeX does it by default, outputting single and double-column figures in independent orders, it is possible to only sort the list of figures by figure number, without changing the output in the main part of the document. The code below does this by ordering lines of the lof file just before \listoffigures is called. The key used to sort is the second item of the second argument of \contentsline, which happens to be the figure number. One could use similar code to sort figures by caption, or whatever other criterion you like.

\documentclass{article}
\usepackage[margin=2cm]{geometry}
\usepackage{imakeidx}
\usepackage{hyperref}
\usepackage{lipsum}

%%%%%%%%%%%%%%%%%%% Sorting a file
\usepackage{catchfile}
\usepackage{expl3, xparse}
\ExplSyntaxOn
\tl_new:N \l_sortfile_tl   % The contents of file #1.
\seq_new:N \l_sortfile_seq % The contents, split at the delimiter #2.
\tl_new:N \l_sortfile_first_tl % Part of the file #1 before first #2.
\iow_new:N \l_sortfile_iow % The output goes there.
\tl_new:N \l_sortfile_a_tl % Used for sorting
\tl_new:N \l_sortfile_b_tl % Used for sorting
\cs_new_protected:Npn \sortfile:nnn #1#2#3
  {
    \IfFileExists {#1}
      { \CatchFileDef { \l_sortfile_tl } {#1} { } }
      { }
    \seq_set_split:NnV \l_sortfile_seq {#2} \l_sortfile_tl
    \seq_pop:NN \l_sortfile_seq \l_sortfile_first_tl
    \seq_sort:Nn \l_sortfile_seq { #3 {##1} {##2} }
    \iow_open:Nn \l_sortfile_iow {#1}
    \tl_if_empty:NF \l_sortfile_first_tl
      { \iow_now:Nx \l_sortfile_iow { \exp_not:V \l_sortfile_first_tl } }
    \seq_map_inline:Nn \l_sortfile_seq
      { \iow_now:Nn \l_sortfile_iow { #2 ##1 } }
    \iow_close:N \l_sortfile_iow
  }
\cs_new_protected:Npn \sortfile_contents_sort:nn #1#2
  {
    \tl_set:Nx \l_sortfile_a_tl { \tl_item:nn {#1} {2} }
    \tl_set:Nx \l_sortfile_b_tl { \tl_item:nn {#2} {2} }
    \int_compare:nNnTF
      { \tl_item:Nn \l_sortfile_a_tl {2} }
      > { \tl_item:Nn \l_sortfile_b_tl {2} }
      { \sort_return_swapped: }
      { \sort_return_same: }
  }
\DeclareDocumentCommand{\sortfile}{mmm}
  { \sortfile:nnn {#1} {#2} {#3} }
\DeclareDocumentCommand{\contentssort}{mm}
  { \sortfile_contents_sort:nn {#1} {#2} }
\ExplSyntaxOff
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
\sortfile{\jobname.lof}{\contentsline}{\contentssort}
\listoffigures
\twocolumn
\lipsum[1-5]
\begin{figure}\footnotesize\lipsum[2]\caption{First figure}\end{figure}
\lipsum[6]
\begin{figure*}\footnotesize\lipsum[2]\caption{Second figure}\end{figure*}
\lipsum[7]
\begin{figure}\footnotesize\lipsum[2]\caption{Third figure}\end{figure}
\lipsum[8]
\begin{figure}\footnotesize\lipsum[2]\caption{Fourth figure}\end{figure}
\lipsum[9-15]
\end{document}