Skip to content

Instantly share code, notes, and snippets.

@jlapier
Created September 21, 2011 16:41
Show Gist options
  • Save jlapier/1232593 to your computer and use it in GitHub Desktop.
Save jlapier/1232593 to your computer and use it in GitHub Desktop.
sort objects with mixed alpha and numerical strings so that "A 10" follows "A 9"
// a simpler version in javascript that actually zero-pads numbers in
// the strings so we can sort properly
// this one uses underscore.js, but you get the picture
// in this example, we have a bunch of text_document objects to sort
sorted = _(text_documents).sortBy(
// the zero padding is to make "Chap 9" come before "Chap 10"
function(td) { return [td.name.replace(/\d+/, function(m) { return zeroPad(m, 99) } )]; }
);
function zeroPad( number, width ) {
width -= number.toString().length;
if ( width > 0 ) {
return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
}
return number;
}
class MyObject
# make sure you know what field you're sorting on - in this case we're using 'name'
attr_accessor :name
# this will sort at multiple levels, for example: "Plan 12:12", "Plan 12:9", "Plan 6:3" will
# sort as "Plan 6:3", "Plan 12:9", "Plan 12:12" instead of ruby's default string sort
def <=>(other)
if name.match(/\d/) and other.name.match(/\d/) and name.gsub(/\d+/,'') == other.name.gsub(/\d+/,'')
my_nums = name.scan(/\d+/).map(&:to_i)
other_nums = other.name.scan(/\d+/).map(&:to_i)
my_nums.each_with_index do |n, i|
n < other_nums[i] && (return -1)
n > other_nums[i] && (return 1)
end
else
name < other.name && (return -1)
name > other.name && (return 1)
end
0
end
end
@jrissler
Copy link

Nice that's much cleaner. I was just in the process of making that a lot shorter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment