Skip to content

Instantly share code, notes, and snippets.

@chaimleib
Last active January 26, 2019 00:08
Show Gist options
  • Save chaimleib/b2f3f6ab9e766dc65d32 to your computer and use it in GitHub Desktop.
Save chaimleib/b2f3f6ab9e766dc65d32 to your computer and use it in GitHub Desktop.
sort strings containing numbers naturally
cmp = (a, b) ->
if a > b then return 1
if a < b then return -1
return 0
numeralizeRgx = /(_+)|([0-9]+)|([^0-9_]+)/g
naturalCmp = (a, b) ->
# Thanks, @georg on stackoverflow.com!
# http://stackoverflow.com/questions/15478954/sort-array-elements-string-with-numbers-natural-sort
ax = []
bx = []
a.replace(numeralizeRgx, (_, $1, $2, $3) -> ax.push([$1 || "", $2 || Infinity, $3 || ""]) )
b.replace(numeralizeRgx, (_, $1, $2, $3) -> bx.push([$1 || "", $2 || Infinity, $3 || ""]) )
while(ax.length && bx.length)
an = ax.shift()
bn = bx.shift()
nn = cmp(an[0], bn[0]) || (an[1] - bn[1]) || cmp(an[2], bn[2])
if nn then return nn
return ax.length - bx.length
var chunkRgx = /(_+)|([0-9]+)|([^0-9_]+)/g;
function naturalCompare(a, b) {
var ax = [], bx = [];
a.replace(chunkRgx, function(_, $1, $2, $3) {
ax.push([$1 || "0", $2 || Infinity, $3 || ""])
});
b.replace(chunkRgx, function(_, $1, $2, $3) {
bx.push([$1 || "0", $2 || Infinity, $3 || ""])
});
while(ax.length && bx.length) {
var an = ax.shift();
var bn = bx.shift();
var nn = an[0].localeCompare(bn[0]) ||
(an[1] - bn[1]) ||
an[2].localeCompare(bn[2]);
if(nn) return nn;
}
return ax.length - bx.length;
}
module NaturalSort
def self.cmp(a, b)
return 1 if a > b
return -1 if a < b
0
end
Numeralizer = /(_+)|([0-9]+)|([^0-9_]+)/
Infinity = Float::INFINITY
def self.natural_cmp(a, b)
ax = []
bx = []
a.gsub(Numeralizer) do
ax << [$1 || '', $2 && !$2.empty? && $2.to_i || Infinity, $3 || '']
end
b.gsub(Numeralizer) do
bx << [$1 || '', $2 && !$2.empty? && $2.to_i || Infinity, $3 || '']
end
while ax.length && bx.length do
an = ax.shift
bn = bx.shift
nn = cmp an[0], bn[0]
nn = an[1] - bn[1] if nn.zero?
nn = 0 if nn.is_a?(Float) && nn.nan?
nn = cmp an[2], bn[2] if nn.zero?
return nn unless nn.zero?
end
ax.length - bx.length
end
def self.natural_sort(l)
l.sort{|a, b| natural_cmp(a, b)}
end
end
test = [
"img12.png",
"img10.png",
"img2.png",
"img1.png",
"img101.png",
"img101a.png",
"abc10.jpg",
"abc10",
"abc2.jpg",
"20.jpg",
"20",
"abc",
"abc2",
"_abc",
"_ab_c",
"_ab__c",
"_abc_d",
"ab_",
"abc_",
"_ab_cd",
""
];
test.sort(naturalCompare)
document.write("<pre>" + JSON.stringify(test,0,3));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment