0

I'm using natbib and an "apacite" bibliography style, in a report document class. I can easily do multiple cites. For example:

\citep{hilary2019, james2013}

Gives me:

(Hilary et al., 2019; D. A. James, 2013)

My question: I have many multiple citations like the above throughout my document, and I would like to order them by date (oldest to newest). I am not talking about the actual biblography, I am pointing to the example at the above. So for example, the above becomes:

\citep{hilary2019,james2013}

Should give me:

(D. A. James, 2013; Hilary et al., 2019)

Is there a way to automatise this? Rather than me having to go through each command and order my citations.

Any help would be great. Thank you!

1
  • 1
    Hi there, I'm Tom from the Overleaf Support Team. Note that I removed the overleaf as this is not directly Overleaf-related. I also think that natbib doesn't support sorting cites by year; for that you'll probably have to switch to biblatex, but I'm not an expert on biblatex really. Either way, it would be helpful if you provided a minimal working example that showed your setup. – yo' Jun 16 '20 at 14:39
1

natbib has a sort option that allows you to sort \citep/\citet calls in the order the entries appear in the bibliography.

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[sort]{natbib}
\bibliographystyle{plainnat}

\begin{filecontents}{\jobname.bib}
@book{aardvark,
  author  = {Anne Aardvark},
  title   = {Ardvarking},
  year    = {2020},
}
@book{zebra,
  author  = {Zoe Zebra},
  title   = {Zebraing},
  year    = {2010},
}
\end{filecontents}


\begin{document}
\citep{zebra,aardvark}

\citep{aardvark,zebra}

\bibliography{\jobname}
\end{document}

[Aardvark, 2020, Zebra, 2010]//[Aardvark, 2020, Zebra, 2010]


If you want to sort citations differently than the bibliography, some additional work is needed. I have demonstrated this for apalike in In-text citation sorted according to publication year with apalike bibliography style.

First we need to modify the .bst file in a way to share the expected citation sort order with us. That can be done by adding

FUNCTION {sort.again}
{
  year field.or.null sortify
  "   "
  * 
  sort.label
  *
  'sort.key$ :=
}

ITERATE {sort.again}

SORT

EXECUTE {newline$}

FUNCTION {produce.sortlist}
{
  "\sortentry{"
  cite$
  *
  "}"
  *
  write$
  newline$
}

ITERATE {produce.sortlist}

to the end of a renamed copy of the .bst file.

For plainnat.bst the modified plainnat-sortcites.bst would look like https://gist.github.com/moewew/783c43bd536de4198d5f5166c886fb61. The exact details can vary from style to style.

Then we need document-level code that can extract the sorting information from the .bbl file and use it for sorting. The following code is only slightly modified code from natbib.sty.

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[sort]{natbib}
\bibliographystyle{plainnat-sortcites}

\usepackage{etoolbox}

\makeatletter
\newcommand*{\sortentry}[1]{%
  \if@filesw
    \immediate\write\@auxout{\string\scNAT@aux@sortentry{#1}}%
  \fi}
\newcommand*{\scNAT@aux@sortentry}{%
  \listgadd{\scNAT@bibsortlist}}
\newcommand*{\scNAT@bibsortlist}{}


\newcommand*{\scNAT@citekeys}{}

\newcommand*{\scNAT@writetocitelistsort}[1]{%
  \ifinlist{#1}{\scNAT@citekeys}
    {\ifdefvoid{\NAT@cite@list}
       {\def\NAT@cite@list{#1}}
       {\expandafter\def\expandafter\NAT@cite@list\expandafter{\NAT@cite@list,#1}}%
     \listgadd{\scNAT@foundkeys}{#1}}
    {}}

% Let's be paranoid: we might have dropped an item that
% has not made it to the bibliography yet
\newcommand*{\scNAT@writetocitelistforgotten}[1]{%
  \ifinlist{#1}{\scNAT@foundkeys}
    {}
    {\ifdefvoid{\NAT@cite@list}
       {\def\NAT@cite@list{#1}}
       {\expandafter\def\expandafter\NAT@cite@list\expandafter{\NAT@cite@list,#1}}}}

\newcommand*{\scNAT@sortcites}[1]{%
  \let\NAT@cite@list\@empty
  \let\scNAT@citekeys\@empty
  \let\scNAT@foundkeys\@empty
  \forcsvlist{\listadd{\scNAT@citekeys}}{#1}%
  \forlistloop{\scNAT@writetocitelistsort}{\scNAT@bibsortlist}%
  \forlistloop{\scNAT@writetocitelistforgotten}{\scNAT@citekeys}%
}

\def\NAT@citex%
  [#1][#2]#3{%
  \NAT@reset@parser
  \NAT@sort@cites{#3}%
  \scNAT@sortcites{#3}%<- this is new
  \NAT@reset@citea
  \@cite{\let\NAT@nm\@empty\let\NAT@year\@empty
    \@for\@citeb:=\NAT@cite@list\do
    {\@safe@activestrue
     \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
     \@safe@activesfalse
     \@ifundefined{b@\@citeb\@extra@b@citeb}{\@citea%
       {\reset@font\bfseries ?}\NAT@citeundefined
                 \PackageWarning{natbib}%
       {Citation `\@citeb' on page \thepage \space undefined}\def\NAT@date{}}%
     {\let\NAT@last@nm=\NAT@nm\let\NAT@last@yr=\NAT@year
      \NAT@parse{\@citeb}%
      \ifNAT@longnames\@ifundefined{bv@\@citeb\@extra@b@citeb}{%
        \let\NAT@name=\NAT@all@names
        \global\@namedef{bv@\@citeb\@extra@b@citeb}{}}{}%
      \fi
     \ifNAT@full\let\NAT@nm\NAT@all@names\else
       \let\NAT@nm\NAT@name\fi
     \ifNAT@swa\ifcase\NAT@ctype
       \if\relax\NAT@date\relax
         \@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}\NAT@date}%
       \else
         \ifx\NAT@last@nm\NAT@nm\NAT@yrsep
            \ifx\NAT@last@yr\NAT@year
              \def\NAT@temp{{?}}%
              \ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
               {Multiple citation on page \thepage: same authors and
               year\MessageBreak without distinguishing extra
               letter,\MessageBreak appears as question mark}\fi
              \NAT@hyper@{\NAT@exlab}%
            \else\unskip\NAT@spacechar
              \NAT@hyper@{\NAT@date}%
            \fi
         \else
           \@citea\NAT@hyper@{%
             \NAT@nmfmt{\NAT@nm}%
             \hyper@natlinkbreak{%
               \NAT@aysep\NAT@spacechar}{\@citeb\@extra@b@citeb
             }%
             \NAT@date
           }%
         \fi
       \fi
     \or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
     \or\@citea\NAT@hyper@{\NAT@date}%
     \or\@citea\NAT@hyper@{\NAT@alias}%
     \fi \NAT@def@citea
     \else
       \ifcase\NAT@ctype
        \if\relax\NAT@date\relax
          \@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
        \else
         \ifx\NAT@last@nm\NAT@nm\NAT@yrsep
            \ifx\NAT@last@yr\NAT@year
              \def\NAT@temp{{?}}%
              \ifx\NAT@temp\NAT@exlab\PackageWarningNoLine{natbib}%
               {Multiple citation on page \thepage: same authors and
               year\MessageBreak without distinguishing extra
               letter,\MessageBreak appears as question mark}\fi
              \NAT@hyper@{\NAT@exlab}%
            \else
              \unskip\NAT@spacechar
              \NAT@hyper@{\NAT@date}%
            \fi
         \else
           \@citea\NAT@hyper@{%
             \NAT@nmfmt{\NAT@nm}%
             \hyper@natlinkbreak{\NAT@spacechar\NAT@@open\if*#1*\else#1\NAT@spacechar\fi}%
               {\@citeb\@extra@b@citeb}%
             \NAT@date
           }%
         \fi
        \fi
       \or\@citea\NAT@hyper@{\NAT@nmfmt{\NAT@nm}}%
       \or\@citea\NAT@hyper@{\NAT@date}%
       \or\@citea\NAT@hyper@{\NAT@alias}%
       \fi
       \if\relax\NAT@date\relax
         \NAT@def@citea
       \else
         \NAT@def@citea@close
       \fi
     \fi
     }}\ifNAT@swa\else\if*#2*\else\NAT@cmt#2\fi
     \if\relax\NAT@date\relax\else\NAT@@close\fi\fi}{#1}{#2}}
\makeatother

\begin{filecontents}{\jobname.bib}
@book{aardvark,
  author  = {Anne Aardvark},
  title   = {Ardvarking},
  year    = {2020},
}
@book{zebra,
  author  = {Zoe Zebra},
  title   = {Zebraing},
  year    = {2010},
}
\end{filecontents}


\begin{document}
\citep{zebra,aardvark}

\citep{aardvark,zebra}

\bibliography{\jobname}
\end{document}

(Zebra, 2010; Aardvark, 2020)//(Zebra, 2010; Aardvark, 2020)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.