title: How to sort by Library of Congress Classification (LCC) number in R
body: <p>Library of Congress Classification numbers are used in libraries to give call numbers to things so they be ordered on the shelf. They can be simple or quite complex, with a few mandatory parts but many optional. (See "entering call numbers in 050" on <a href="http://www.oclc.org/bibformats/en/0xx/050.html" rel="nofollow noreferrer">050 Library of Congress Call Number</a> for how they break down, or <a href="https://github.com/billdueber/lc_callnumber" rel="nofollow noreferrer">lc_callnumber</a> for a Ruby tool that sorts them.)</p>
  
  <p>I would like to sort by LCC number in R. I've looked at <a href="https://stackoverflow.com/q/7515377/854346">Sort a list of nontrivial elements in R</a> and <a href="https://stackoverflow.com/q/37676537/854346">Sorting list of list of elements of a custom class in R?</a> but haven't got it figured out.</p>
  
  <p>Here are four call numbers, entered in sorted order:</p>
  
  <pre><code>call_numbers &lt;- c("QA 7 H3 1992", "QA 76.73 R3 W53 2015", "QA 90 H33 2016", "QA 276.45 R3 A35 2010")
  </code></pre>
  
  <p><code>sort</code> sorts them by character, so 276 &lt; 7 &lt; 76.73 &lt; 90.</p>
  
  <pre><code>&gt; sort(call_numbers)
  [1] "QA 276.45 R3 A35 2010" "QA 7 H3 1992"          "QA 76.73 R3 W53 2015"  "QA 90 H33 2016"       
  </code></pre>
  
  <p>To sort them properly I think I'd have to define a class and then some methods on it, like this:</p>
  
  <pre><code>library(stringr)
  class(call_numbers) &lt;- "LCC"
  
  ## Just pick out the letters and digits for now, leave the rest
  ## until sorting works, then work down more levels.
  lcc_regex &lt;- '([[:alpha:]]+?) ([[:digit:]\\.]+?) (.*)'
  
  "&lt;.LCC" &lt;- function(x, y) {
      x_lcc &lt;- str_match(x, lcc_regex)
      y_lcc &lt;- str_match(y, lcc_regex)
      if(x_lcc[2] &lt; y_lcc[2]) return(x)
      if(as.integer(x_lcc[3]) &lt; as.integer(y_lcc[3])) return(x)
  }
  "==.LCC" &lt;- function(x, y) {
      x_lcc &lt;- str_match(x, lcc_regex)
      y_lcc &lt;- str_match(y, lcc_regex)
      x_lcc[2] == y_lcc[2] &amp;&amp; x_lcc[3] == y_lcc[3]
  }
  
  "&gt;.LCC" &lt;- function(x, y) {
      x_lcc &lt;- str_match(x, lcc_regex)
      y_lcc &lt;- str_match(y, lcc_regex)
      if(x_lcc[2] &gt; y_lcc[2]) return(x)
      if(as.integer(x_lcc[3]) &gt; as.integer(y_lcc[3])) return(x)
  }
  </code></pre>
  
  <p>This doesn't change the sort order. I haven't defined a subset method (<code>"[.myclass"</code>) because I have no idea what it should be.</p>