4

How to sort the bibliography alphabetically by their labels

\begin{the bibliography}{10}
\bibitem[Polchinski, 1984]{jpol}
Polchinski,~J.
\newblock{(1984)},
\newblock Renormalization group and effective lagrangians.
\newblock {\textbf{ Nuclear Physics B}}, 231:269--295.

\bibitem[Binney \textit{et al.}, 1992]{binney}
Binney,~J.~J., Dowrick,~N.~J.,  Fisher,~A.~J. and Newman,~M.~E.~J.
\newblock{(1992)},
\newblock \textbf{The Theory of critical phenomena: An introduction to the renormalization group}.
\newblock {Clarendon Press, Oxford, UK}.

\bibitem[Politzer, 1974]{politzer}
Politzer,~H.~D.
\newblock{(1974)},
\newblock Asymptotic freedom: An approach to strong interactions.
\newblock {\textbf{ Physics Reports}}, 14(4):129--180.
\end {the bibliography}

i.e. I need the order to be Binney then Polchinski then Politzer (in the above example)

Nils L
  • 9,716
Riad
  • 41

2 Answers2

12

Update the l3kernel and l3experimental packages. Here is some code that defines a sortbibliography environment, which (1) captures everything until \end{sortbibliography} (using the environ package, which you probably already have), (2) splits what it found (\BODY) into individual items (at every \bibitem), (3) removes whatever was before the first \bibitem (and makes sure that was empty), (4) sorts the items in lexicographic order, (5) typesets everything within the environment of your choice (here I used thebibliography, but you seem to have a the bibliography environment in your setup. This should be fast for up to a few thousand items, although I have not tested it extensively.

\documentclass{article}
\usepackage{environ}
\usepackage{expl3}
\ExplSyntaxOn
\seq_new:N \l_riad_bib_seq % bibliography, split at \bibitem commands
\tl_new:N \l_riad_pre_tl   % part before the first \bibitem
\prg_new_conditional:Npnn \riad_str_compare:nNn #1#2#3 { TF }
  {
    % Comparing two entries in the bibliography is done using
    % the primitive \pdfstrcmp (for XeTeX, use \strcmp, for LuaTeX, use
    % \pdf@strcmp from Oberdiek's package pdftexcmds), which compares
    % strings in lexicographic order.
    %
    \if_int_compare:w
        \pdfstrcmp { \exp_not:n {#1} } { \exp_not:n {#3} } #2 \c_zero_int
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
\NewEnviron{sortbibliography}[2]
  {
    \begin{#1}{#2}
      \seq_set_split:NnV \l_riad_bib_seq { \bibitem } \BODY
      \seq_pop:NN \l_riad_bib_seq \l_riad_pre_tl
      \tl_remove_all:Nn \l_riad_pre_tl { \par } % Error checking: only \par and
      \tl_remove_all:Nn \l_riad_pre_tl { ~ }    % spaces before first \bibitem.
      \tl_if_empty:NF \l_riad_pre_tl            % Otherwise, complain about the
        {                                       % tokens found before \bibitem.
          \msg_error:nnxxx { riad } { junk-before }
            { \token_to_str:N \bibitem }
            { sortbibliography }
            { \tl_to_str:N \l_riad_pre_tl }
        }
      \seq_sort:Nn \l_riad_bib_seq
        {
          \riad_str_compare:nNnTF {##1} > {##2}
            { \sort_return_swapped: }
            { \sort_return_same: }
        }
      \seq_map_inline:Nn \l_riad_bib_seq { \bibitem ##1 }
    \end{#1}
  }
\msg_new:nnn { riad } { junk-before }
  { Extra~'#3'~before~the~first~'#1'~in~environment~'#2'. }
\ExplSyntaxOff
\begin{document}
\begin{sortbibliography}{thebibliography}{10}
\bibitem[Polchinski, 1984]{jpol}
Polchinski,~J.
\newblock{(1984)},
\newblock Renormalization group and effective lagrangians.
\newblock {\textbf{ Nuclear Physics B}}, 231:269--295.

\bibitem[Binney \textit{et al.}, 1992]{binney} Binney,~J.~J., Dowrick,~N.~J., Fisher,~A.~J. and Newman,~M.~E.~J. \newblock{(1992)}, \newblock \textbf{The Theory of critical phenomena: An introduction to the renormalization group}. \newblock {Clarendon Press, Oxford, UK}.

\bibitem[Politzer, 1974]{politzer} Politzer,~H.~D. \newblock{(1974)}, \newblock Asymptotic freedom: An approach to strong interactions. \newblock {\textbf{ Physics Reports}}, 14(4):129--180. \end{sortbibliography} \end{document}

mbert
  • 4,171
  • I defined a similar \string_compare:nnn(TF) conditional in this answer. By the way, \pdftex_strcmp:D adapts itself to the engine used. – egreg May 18 '13 at 13:15
  • @egreg: I know \pdf_strcmp:D adapts, but I am wary of suggesting it to users, since it is a Do not use command. I don't really want to provide a \sort_lexicographic wrapper in l3sort because the proper approach would need to handle locales, which I am not ready to do :(. – Bruno Le Floch May 18 '13 at 13:55
  • Maybe a \string_compare_ascii:nnn(TF) function might be handy for simple tasks. – egreg May 18 '13 at 13:58
  • @BrunoLeFloch \c_zero seems to be deprecated too. – tambre Dec 29 '18 at 11:56
  • @tambre: true but it will be removed in 2019 so I'll deal with this another day, sorry. – Bruno Le Floch Dec 30 '18 at 01:22
  • Those codes about expl3 for sorting bibliography did not work in new version texlive onward 2021, so could you help provide related solution for the new version? Best, Regards – Xiu Li Dec 26 '23 at 03:58
  • @XiuLi Someone fixed it before I got to read your comment. The constant \c_zero had to be renamed to \c_zero_int. – Bruno Le Floch Dec 26 '23 at 22:25
3

You're in trouble here. You've decided to create a manual bibliography rather than use bib(la)tex -- which might be justified in certain circumstances, but probaly the most fundamental feature of a manual bibliography is that the sorting is going to be manual as well ...since there's simply no tool involved that would be capable of doing the sorting for you.

One option that might help you is the one suggested by Jubobs. A second one is to give your thebibliography a format that can be processed by some third-party tool that's capable of sorting plain-text lines: such as any spreadsheet application, or, if you're on Windows, WinSorter (a nice multi-purpose tool for all kinds of text manipulation), or maybe even the TeX editor you're already using (e.g. WinEdt). After choosing one such a tool, try the following procedure:

(1) use a search and replace to remove everything that precedes the strings that you want your bib sorted by. I guess in your case this would be: \bibitem[ -- so the lines now start with Binney etc. (RegExs might be helpful or necessary here).

(2) use a 2nd search and replace to remove all the line breaks that occur within an item, replacing them with some character or string that's not used otherwise, such as -- so that every bib item is conflated into one single line.

Before:

\bibitem[Binney \textit{et al.}, 1992]{binney}
Binney,~J.~J., Dowrick,~N.~J.,  Fisher,~A.~J. and Newman,~M.~E.~J.
\newblock{(1992)},
\newblock \textbf{The Theory of critical phenomena: An introduction to the renormalization group}.
\newblock {Clarendon Press, Oxford, UK}.

After:

Binney \textit{et al.}, 1992]{binney} ¶ Binney,~J.~J., Dowrick,~N.~J.,  Fisher,~A.~J. and Newman,~M.~E.~J. ¶ \newblock{(1992)}, ¶ \newblock \textbf{The Theory of critical phenomena: An introduction to the renormalization group}. ¶ \newblock {Clarendon Press, Oxford, UK}.

(3) Use the sorting tool of your choice to sort the lines.

(4) Use the reverse of steps 2 and 1 to put your bibliography back into its original format.

(5) Consider using an automated bibliography with for your next paper :)

David Carlisle
  • 757,742
Nils L
  • 9,716