There are workable answers for sorting an array of hashes and for natural sorting, but what is the best way to do both at once?
my_array = [ {"id":"some-server-1","foo":"bar"},{"id":"some-server-2","foo":"bat"},{"id":"some-server-10","foo":"baz"} ]
I would like to sort on “id” such that the final ordering is:
some-server-1
some-server-2
some-server-10
I feel like there must be a clever and efficient way to do this, though personally I don’t need to break any speed records and will only be sorting a few hundred items. Can I implement a comparison function in sort_by?
First of all, your
my_arrayis JavaScript/JSON so I’ll assume that you really have this:Then you just need to
sort_bythe numeric suffix of the'id'values:If the “some-server-” prefixes aren’t always “some-server-” then you could try something like this:
That would split the
'id'values into numeric and non-numeric pieces, convert the numeric pieces to integers, and then compare the mixed string/integers arrays using the Array<=>operator (which compares component-wise); this will work as long as the numeric and non-numeric components always match up. This approach would handle this:but not this:
If you need to handle this last case then you’d need to compare the arrays entry-by-entry by hand and adjust the comparison based on what you have. You could still get some of the advantages of the
sort_bySchwartzian Transform with something like this (not very well tested code):The basic idea here is to push the comparison noise off to another class to keep the
sort_byfrom degenerating into an incomprehensible mess. Then we use the same scanning as before to break the strings into pieces and implement the array<=>comparator by hand. If we have two things of the same class then we let that class’s<=>deal with it otherwise we force both components to String and compare them as such. And we only care about the first non-0 result.