Last active
July 17, 2020 00:46
-
-
Save wevre/7b437d56e6c1d798e382b75bed35d5d3 to your computer and use it in GitHub Desktop.
Natural sort comparator in Clojure/ClojureScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns natural-compare | |
^{:author "Mike Weaver" | |
:see-also [["https://gist.github.com/wilkerlucio/db54dc83a9664124f3febf6356f04509" | |
"Alphabetical/Natural sorting in Clojure/Clojurescript"]] | |
:doc "A comparator for natural sorting."} | |
(:require [clojure.string :as str])) | |
(defn split-digits | |
"Splits string into sequence of alternating text and numbers." | |
[s] | |
(let [parse-int #(Long/parseLong %) ;; for cljs, use #(js/parseInt %) | |
text (str/split s #"\d+") | |
nums (mapv parse-int (re-seq #"\d+" s))] | |
;; Padding `text` and `nums` with "" and -1, respectively, ensures resulting | |
;; sequence will start with text, end with a number, and consistently | |
;; alternate inbetween. The pad values sort lower than 'legit' values, so | |
;; when one string is a prefix of another, the shorter one sorts first. | |
(interleave (conj text "") (conj nums -1)))) | |
(defn natural-compare | |
"Compares two strings with natural sorting." | |
[a b] | |
(or (->> (map compare (split-digits a) (split-digits b)) | |
(drop-while zero?) | |
first) | |
0)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment